コンテンツにスキップ

JavaScript/非同期反復可能オブジェクト

出典: フリー教科書『ウィキブックス(Wikibooks)』


非同期反復可能オブジェクト

[編集]

非同期反復可能オブジェクト は、JavaScriptで非同期処理を伴うデータの反復を可能にするオブジェクトです。このオブジェクトは、Symbol.asyncIterator プロパティを持ち、非同期反復子(AsyncIterator)を返すメソッドを実装する必要があります。これにより、for await...of ループなどで非同期データを扱うことができます。

特徴

[編集]
  • 非同期処理: 非同期反復可能オブジェクトは非同期処理を扱うために設計されています。
  • Symbol.asyncIterator: この特定のシンボルを使用して非同期反復子を取得します。
  • Promise対応: 非同期反復子の next() メソッドは常に Promise を返します。

非同期反復可能オブジェクトの作成

[編集]

基本例

[編集]

以下は、非同期反復可能オブジェクトの基本的な実装例です。

const myAsyncIterable = {
  [Symbol.asyncIterator]() {
    let count = 0;
    return {
      async next() {
        if (count < 3) {
          return { value: count++, done: false };
        } else {
          return { value: undefined, done: true };
        }
      }
    };
  }
};

(async () => {
  for await (const value of myAsyncIterable) {
    console.log(value); // 0, 1, 2
  }
})();

非同期データの処理

[編集]

非同期データソースを処理するための非同期反復可能オブジェクトの例です。

const fetchData = async (id) => {
  return new Promise((resolve) => {
    setTimeout(() => resolve(`Data ${id}`), 1000);
  });
};

const asyncDataIterable = {
  [Symbol.asyncIterator]() {
    let id = 1;
    return {
      async next() {
        if (id <= 3) {
          const value = await fetchData(id++);
          return { value, done: false };
        } else {
          return { value: undefined, done: true };
        }
      }
    };
  }
};

(async () => {
  for await (const data of asyncDataIterable) {
    console.log(data); // Data 1, Data 2, Data 3
  }
})();

使用方法

[編集]

for await...of

[編集]

非同期反復可能オブジェクトは for await...of ループで使用できます。この構文を使用すると、非同期操作を順次実行しながら反復処理を行えます。

(async () => {
  for await (const value of asyncIterable) {
    console.log(value);
  }
})();

注意点

[編集]
  • 同期と非同期の違い: 同期反復可能オブジェクト(Symbol.iterator を使用)と非同期反復可能オブジェクト(Symbol.asyncIterator を使用)は別物です。両者を混同しないよう注意してください。
  • Promiseの利用: 非同期反復子の next() メソッドは必ず Promise を返す必要があります。

実用例

[編集]

ファイルの逐次読み取り

[編集]

以下は、非同期反復可能オブジェクトを使用してファイルを逐次読み取る例です。

const fileReader = {
  [Symbol.asyncIterator]() {
    const lines = ['Line 1', 'Line 2', 'Line 3'];
    let index = 0;
    return {
      async next() {
        if (index < lines.length) {
          // 模擬的に非同期処理を実行
          await new Promise(resolve => setTimeout(resolve, 500));
          return { value: lines[index++], done: false };
        } else {
          return { value: undefined, done: true };
        }
      }
    };
  }
};

(async () => {
  for await (const line of fileReader) {
    console.log(line); // Line 1, Line 2, Line 3
  }
})();

関連項目

[編集]

参考

[編集]