This blog post describes how for-await-of handles synchronous iterables. for-await-of is a core construct of asynchronous iteration. You can read up on it in the blog post “ES proposal: asynchronous iteration”.

Note: you can run the examples in Node.js 9.2+ via:

node --harmony-async-iteration

Refresher: asynchronous iterables #

Asynchronous iterables return asynchronous iterators, whose method next() returns Promises for {value, done} objects:

async function * asyncGen ( ) { yield 'a' ; yield 'b' ; } const iter = asyncGen()[ Symbol .asyncIterator](); iter.next().then( x => console .log(x)); iter.next().then( x => console .log(x)); iter.next().then( x => console .log(x));

Synchronous iterables and for-await-of #

Synchronous iterables return synchronous iterators, whose method next() returns {value, done} objects. for-await-of handles synchronous iterables by converting them to asynchronous iterables. Each iterated value is converted to a Promise (or left unchanged if it already is a Promise) via Promise.resolve() . That is, for-await-of works for iterables over Promises and over normal values. The conversion looks like this:

const nextResult = Promise .resolve(valueOrPromise) .then( x => ({ value : x, done : false }));

Two more ways of looking at the conversion are:

Iterable<Promise<T>> becomes AsyncIterable<T>

The following object { value : Promise .resolve( 123 ), done : false } is converted to Promise .resolve({ value : 123 , done : false })

Therefore, the following two statements are roughly similar.

for ( const x of await Promise .all(syncIterableOverPromises)); for await ( const x of syncIterableOverPromises);

The second statement is faster, because Promise.all() only creates the Promise for the Array after all Promises in syncIterableOverPromises are fulfilled. And for-of has to await that Promise. In contrast, for-await-of starts processing as soon as the first Promise is fulfilled.

for-await-of in action #

Iterating over a sync iterable over Promises:

async function main ( ) { const syncIterable = [ Promise .resolve( 'a' ), Promise .resolve( 'b' ), ]; for await ( const x of syncIterable) { console .log(x); } } main();

Iterating over a sync iterable over normal values:

async function main ( ) { for await ( const x of [ 'c' , 'd' ]) { console .log(x); } } main();

Further reading #