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:
interface AsyncIterator<T> {
next(value?: any): Promise<IteratorResult<T>>;
return?(value?: any): Promise<IteratorResult<T>>;
throw?(e?: any): Promise<IteratorResult<T>>;
}
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:
async function* g() {
yield 1;
await sleep(100);
yield* [2, 3];
yield* (async function *() {
await sleep(100);
yield 4;
})();
}
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:
async function f() {
for await (const x of g()) {
console.log(x);
}
}
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 polyfillSymbol.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 theAsyncIterator
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.