๐ŸŽ“ A1Learner
๐Ÿ”
0 of 37 lessons completed

TypeScript Async Iterables

An async iterable is a source that hands out values one at a time, with a pause allowed before each one. A for await loop pulls the values in order until the source reports it is done.

An async generator over a counter

The generator counts to a fixed limit and yields each number. The loop pulls one value at a time, so the printed order is the pull order.

async function* counter(limit: number): AsyncGenerator<number> {
  for (let i = 1; i <= limit; i++) {
    yield i;
  }
}

async function main(): Promise<void> {
  for await (const n of counter(3)) {
    console.log(n);
  }
}

void main();

An AsyncIterable with Symbol.asyncIterator

The object returns an iterator whose next method hands out a promise per value. Two fixed letters come out in list order.

const letters: AsyncIterable<string> = {
  [Symbol.asyncIterator](): AsyncIterator<string> {
    const items: string[] = ['a', 'b'];
    let index = 0;
    return {
      next(): Promise<IteratorResult<string>> {
        if (index < items.length) {
          const value: string = items[index];
          index++;
          return Promise.resolve({ value, done: false });
        }
        return Promise.resolve({ value: undefined, done: true });
      },
    };
  },
};

async function main(): Promise<void> {
  for await (const letter of letters) {
    console.log(letter);
  }
}

void main();

A plain array under for await

A sync iterable needs no changes to sit under for await. The loop reads the array members in order.

async function main(): Promise<void> {
  const words: string[] = ['red', 'blue'];

  for await (const word of words) {
    console.log(word);
  }
}

void main();

Example

async function* ticks(): AsyncGenerator<number> {
  yield 10;
  yield 20;
  yield 30;
}

async function main(): Promise<void> {
  let total = 0;

  for await (const tick of ticks()) {
    total = total + tick;
    console.log('tick ' + tick);
  }

  console.log('total ' + total);
}

void main();

Key points

  • An async generator is written with async function* and pauses at each yield until the next value is pulled.
  • The method keyed by Symbol.asyncIterator marks an object as an async iterable source.
  • A for await loop works on async iterables and on plain sync iterables such as arrays.
  • Each pull runs in order, so a fixed source gives fixed output.

In this example, the generator yields three fixed values, the loop prints each pull as it arrives, and the running total proves the order.

Note

Async iteration suits values that arrive over time, such as pages, chunks, or events.

Try it Yourself

Edit the code, then press Run.

Running is simulated ยท TypeScript Playground

Exercise

What does a for await loop do with an async generator?