Async Iteration

TypeScript 2.3 adds support for the async iterators and generators as described by the current TC39 proposal.

Async iterators

The Async Iteration introduces an AsyncIterator, which is similar to Iterator.The difference lies in the fact that the next, return, and throw methods of an AsyncIterator return a Promise for the iteration result, rather than the result itself. This allows the caller to enlist in an asynchronous notification for the time at which the AsyncIterator has advanced to the point of yielding a value.An AsyncIterator has the following shape:

  1. interface AsyncIterator<T> {
  2. next(value?: any): Promise<IteratorResult<T>>;
  3. return?(value?: any): Promise<IteratorResult<T>>;
  4. throw?(e?: any): Promise<IteratorResult<T>>;
  5. }

An object that supports async iteration is said to be “iterable” if it has a Symbol.asyncIterator method that returns an AsyncIterator object.

Async Generators

The Async Iteration proposal introduces “Async Generators”, which are async functions that also can be used to yield partial computation results. Async Generators can also delegate calls via yield* to either an iterable or async iterable:

  1. async function* g() {
  2. yield 1;
  3. await sleep(100);
  4. yield* [2, 3];
  5. yield* (async function *() {
  6. await sleep(100);
  7. yield 4;
  8. })();
  9. }

As with Generators, Async Generators can only be function declarations, function expressions, or methods of classes or object literals. Arrow functions cannot be Async Generators. Async Generators require a valid, global Promise implementation (either native or an ES2015-compatible polyfill), in addition to a valid Symbol.asyncIterator reference (either a native symbol or a shim).

The for-await-of Statement

Finally, ES2015 introduced the for..of statement as a means of iterating over an iterable.Similarly, the Async Iteration proposal introduces the for..await..of statement to iterate over an async iterable:

  1. async function f() {
  2. for await (const x of g()) {
  3. console.log(x);
  4. }
  5. }

The for..await..of statement is only legal within an Async Function or Async Generator.

Caveats

  • Keep in mind that our support for async iterators relies on support for Symbol.asyncIterator to exist at runtime.You may need to polyfill Symbol.asyncIterator, which for simple purposes can be as simple as: (Symbol as any).asyncIterator = Symbol.asyncIterator || Symbol.from("Symbol.asyncIterator");
  • You also need to include esnext in your —lib option, to get the AsyncIterator declaration if you do not already have it.
  • Finally, if your target is ES5 or ES3, you’ll also need to set the —downlevelIterators flag.