Glossary / Async generators

Async generators

An async generator (async function*) combines generator suspension with asynchronous iteration. It produces an async iterator whose next() calls return Promises for iterator-result objects. This lets a producer yield records on demand while awaiting network, storage, or other asynchronous work between values.

Consumption and backpressure

async function* pages(fetchPage) {
  for (let page = 1; ; page++) {
    const result = await fetchPage(page);
    if (result.done) return;
    yield result.items;
  }
}

for await (const items of pages(fetchPage)) {
  await process(items);
}

for await...of requests one result at a time and awaits it. This can provide natural demand-driven progression, but it does not guarantee the entire upstream system is bounded: fetchers may buffer, producers can spawn parallel work, and a consumer may accumulate yielded values. Cancellation and early break should propagate to underlying resources, often through AbortSignal and finally cleanup.

An async generator can yield ordinary values or Promises; yielded Promises are assimilated as part of async-generator behavior. Errors from awaited operations reject the pending next() Promise and can be caught by the consumer. Define how retry, cancellation, and partial failure work for streams.

Interview questions

  1. How consume an async generator? for await...of or by awaiting iterator.next().
  2. What advantage does it have over collecting all pages first? It yields results incrementally and can react to consumer demand.
  3. Does async iteration automatically bound memory? No; upstream and consumer buffering still matter.
  4. How clean up on early exit? Use finally in the generator and ensure cancellation reaches underlying work.

References