for await...of and Async Generators

Iterates an async iterable — one whose Symbol.asyncIterator produces promises — the async counterpart to for...of.

                for await (const value of asyncIterable) {} / async function* gen() { yield value; }
              

Purpose

for await...of iterates an async iterable — one implementing Symbol.asyncIterator, whose .next() produces promises instead of plain values — awaiting each one automatically. An async generator (async function*) is the easiest way to produce one.

Syntax

async function* fetchPages(baseUrl) {
  let page = 1;
  while (true) {
    const response = await fetch(`${baseUrl}?page=${page}`);
    const data = await response.json();
    if (data.items.length === 0) return;
    yield data.items;
    page++;
  }
}

for await (const items of fetchPages('/api/results')) {
  console.log(`Got ${items.length} items`);
}

Behavior notes

  • for await...of can be used inside an async function on any async iterable — or even on a regular (non-async) iterable of promises, awaiting each one in turn.
  • An async generator combines async/await and yield freely inside the same function body, awaiting intermediate results before yielding a value onward.
  • This is the foundation streaming APIs build on — a ReadableStream’s reader, or a paginated fetch helper, process chunks of data as they arrive instead of buffering an entire response first.

Common mistakes

  • Using a plain for...of on an async iterable — it won’t await the produced promises, yielding unresolved Promise objects instead of their values.
  • Assuming an async generator fetches all pages eagerly — like a regular generator, it only advances as far as something has actually requested, one yield at a time.

Runtime notes

Core ECMAScript (ES2018), identical behavior across every current browser and Node version.

Taught in these lessons

Related reference