AsyncGenerator

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since January 2020.

AsyncGenerator オブジェクトは非同期ジェネレーター関数から返されるもので、非同期反復可能プロトコルと非同期イテレータープロトコルの両方を満たすものです。

非同期ジェネレーターメソッドは、常に Promise オブジェクトを生成します。

AsyncGenerator は隠しクラスの AsyncIterator のサブクラスです。

試してみましょう

コンストラクター

AsyncGenerator コンストラクターはグローバルには利用できません。AsyncGenerator のインスタンスは、非同期ジェネレーター関数から返される必要があります。

js
async function* createAsyncGenerator() {
  yield await Promise.resolve(1);
  yield await Promise.resolve(2);
  yield await Promise.resolve(3);
}
const asyncGen = createAsyncGenerator();
asyncGen.next().then((res) => console.log(res.value)); // 1
asyncGen.next().then((res) => console.log(res.value)); // 2
asyncGen.next().then((res) => console.log(res.value)); // 3

実際、AsyncGeneratorコンストラクターに対応するJavaScriptのエンティティはありません。非同期ジェネレーター関数によって生成されるすべてのオブジェクトによって共有されるプロトタイプオブジェクトである隠しオブジェクトがあるだけです。このオブジェクトはクラスのように見せるために AsyncGenerator.prototype というスタイルで呼ばれることが多いのですが、AsyncGeneratorFunction.prototype.prototype と呼ぶほうが適切でしょう。なぜなら AsyncGeneratorFunction は実際の JavaScript エンティティであるからです。

インスタンスプロパティ

これらのプロパティは AsyncGenerator.prototype で定義されており、すべての AsyncGenerator インスタンスで共有されています。

AsyncGenerator.prototype.constructor

インスタンスオブジェクトを作成したコンストラクター関数。AsyncGenerator インスタンスの場合、初期値は AsyncGeneratorFunction.prototype です。

メモ: AsyncGenerator は生成した非同期ジェネレーター関数を格納しているわけではありません。

AsyncGenerator.prototype[@@toStringTag]

@@toStringTag プロパティの初期値は、文字列 "AsyncGenerator" です。このプロパティは Object.prototype.toString() で使用されます。

インスタンスメソッド

親である AsyncIterator からインスタンスメソッドを継承しています

AsyncGenerator.prototype.next()

Promise を返します。これは、yield 式で返された指定された値で解決されます。

AsyncGenerator.prototype.return()

ジェネレータ本体に現在の停止位置に return 文を挿入したかのように動作します。try...finally ブロックと組み合わせるとジェネレーターを終了し、クリーンアップタスクを実行することができます。

AsyncGenerator.prototype.throw()

ジェネレーター本体の現在の停止位置に throw 文が挿入されたかのように動作します。これは、ジェネレーターにエラー状態を通知し、エラーを処理するか、クリーンアップを実行して自身を終了させることができます。

非同期ジェネレーターの反復処理

次の例では、非同期ジェネレーターを反復処理し、時間間隔が短くなるごとに 1~6 の値をコンソールに出力しています。時刻が変わるたびにプロミスが生成されますが、それは for await...of ループの中で自動的に解決されることに注意してください。

js
// 非同期タスクです。実際にはもっと有益なことを使用していることを
// 想定してください。
function delayedValue(time, value) {
  return new Promise((resolve /*, reject*/) => {
    setTimeout(() => resolve(value), time);
  });
}

async function* generate() {
  yield delayedValue(2000, 1);
  yield delayedValue(100, 2);
  yield delayedValue(500, 3);
  yield delayedValue(250, 4);
  yield delayedValue(125, 5);
  yield delayedValue(50, 6);
  console.log("All done!");
}

async function main() {
  for await (const value of generate()) {
    console.log("value", value);
  }
}

main().catch((e) => console.error(e));

仕様書

Specification
ECMAScript Language Specification
# sec-asyncgenerator-objects

ブラウザーの互換性

BCD tables only load in the browser

関連情報