ES6 has generators that return iterators:
function* range(n) {
    for (let i = 0; i < n; ++i) {
        yield i;
    }
}
for (let x of range(10)) {
    console.log(x);
}
There is a proposal for asynchronous functions that return Promises:
async function f(x) {
    let y = await g(x);
    return y * y;
}
f(2).then(y => {
    console.log(y);
});
So what happens if I combine the two, like this:
async function* ag(n) {
    for (let i = 0; i < n; ++i) {
         yield i;
    }
}
What does it return? Is it Promise<Iterator<Item>>? Iterator<Promise<Item>>? Something else? How do I consume it? I imagine there should be a corresponding for loop, what will iterate over its result asynchronously, something like:
for (await let x of ag(10)) {
    console.log(x);
}
which waits for each item to become available before trying to access the next one.
Promise<Iterator<Item>> or Iterator<Promise<Item>>?Neither. It's still not approved, but current implementations return something else. Kris Kowal has written an about async generators, and references Jafar Husain's AsyncGenerator proposal for ES7. EDIT: We have tc39 proposal and babel support!
Let's define some types (simplified):
interface Iterator<T> {
  Iteration<T> next();
}
type Iteration<T> = { done: boolean, value: T }
We are looking for something that can be used like this:
for (;;) {
    var iteration = await async_iterator.next();
    if (iteration.done) {
        return iteration.value;
    } else {
        console.log(iteration.value);
    }
}
An Iterator<Promise<T>> produces synchronous iterations, whose values are Promises. It could be used like this:
for (;;) {
    var iteration = iterator_promise.next();
    if (iteration.done) {
        return await iteration.value;
    } else {
        console.log(await iteration.value);
    }
}
A Promise<Iterator<T>> is just a regular synchronous iterator, starting in the future:
var iterator = await promise_iterator;
for (;;) {
    var iteration = iterator.next();
    if (iteration.done) {
        return iteration.value;
    } else {
        console.log(iteration.value);
    }
}
So neither Iterator<Promise<T>> nor Promise<Iterator<T>> was suitable. Currently async generators return AsyncIterators instead:
interface AsyncIterator<T> {
  Promise<Iteration<T>> next();
}
Which perfectly makes sense. Moving to the next element of the iterator is the asynchronous operation, and this can be used exactly like we wanted.
Babeljs.io already compiles async generators. Babeljs.io/repl example:
EDIT: No preset on babeljs.io compiles async generators since babel 6, babel-plugin-transform-regenerator supports it with {asyncGenerators:true} option.
EDIT: see transform-async-generator-functions babel 6 plugin.
function delay(timeout, val) {
  return new Promise(resolve => setTimeout(resolve, timeout, val));
}
async function* asyncGenerator() {
  for (var i = 0; i < 5; i++) {
    await delay(500);
    yield i;
  }
}
async function forAwait(iter, fn) {
  for (;;) {
    let iteration = await iter.next();
    if (iteration.done) return iteration.value;
    await fn(iteration.value);
  }
}
async function main() {
  console.log('Started');
  await forAwait(asyncGenerator(), async item => {
    await delay(100);
    console.log(item);
  });
  console.log('End');
}
main();
There is a proposal for a convenient for await loop for async iterators (described at Async iteration):
for await (let line of readLines(filePath)) {
    print(line);
}
Update:
Unfortunately, async-await didn't become a part of ECMAScript 2016. At least await is mentioned a reserved word for future use.
Update:
Related proposals:
Lots have changed since this post was written. Promises, iterators/generators and async/await syntax are all part of the standard. Let's take a look at the evolution of running a simple async operation (e.g. setTimeout) over the different methods.
Let's consider a simple Promise wrapper to the setTimeout function. Then, we can implement a simple Promise chain to console.log messages with a sleep delay.
function sleep(delay) {
    return new Promise(function (resolve, reject) {
        setTimeout(resolve, delay);
    } );
}
console.log('one');
sleep(1000)
.then( function () {
    console.log('two');
    return sleep(1000);
} )
.then( function () {
    console.log('three');
} );
Now let's consider rewriting the above Promise chain using async/await syntax:
function sleep(delay) {
    return new Promise(function (resolve, reject) {
        setTimeout(resolve, delay);
    } );
}
(async function () {
    console.log('one');
    await sleep(1000);
    console.log('two');
    await sleep(1000);
    console.log('three');
})();
Very nice. Prior to new standards, people were using https://babeljs.io to help transpile from the newer JavaScript standards to an earlier version by rewriting await/async with iterator/generator syntax:
function sleep(delay) {
    return new Promise(function (resolve, reject) {
        setTimeout(resolve, delay);
    } );
}
_asyncToGenerator(function *() {
    console.log('one');
    yield sleep(1000);
    console.log('two');
    yield sleep(1000);
    console.log('three');    
})();
function _asyncToGenerator(fn) {
    return function() {
        var self = this,
        args = arguments
        return new Promise(function(resolve, reject) {
            var gen = fn.apply(self, args)
            function _next(value) {
                asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value)
            }
            function _throw(err) {
                asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err)
            }
            _next(undefined)
        })
    }
}
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
    try {
        var info = gen[key](arg)
        var value = info.value
    } catch (error) {
        reject(error)
        return
    }
    if (info.done) {
        resolve(value)
    } else {
        Promise.resolve(value).then(_next, _throw)
    }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With