Result of Asynchronous ES6 Generator

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 suggestion for asynchronous functions that Promises return:

 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, for example:

 async function* ag(n) { for (let i = 0; i < n; ++i) { yield i; } } 

What does he return? Is it a Promise<Iterator<Item>> ? Iterator<Promise<Item>> ? Something other? How to use it? I assume that there should be a corresponding for loop, which will iterate over its result asynchronously, for example:

 for (await let x of ag(10)) { console.log(x); } 

which expects each item to become available before trying to access the next.

+5
source share
2 answers

Promise<Iterator<Item>> or Iterator<Promise<Item>> ?

None. It is still not approved, but current implementations return something else. Chris Koval wrote about asynchronous generators and links Jafar Husain AsyncGenerator Offer for ES7 . EDIT . We have tc39 offer and babel support !

Let 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 as follows:

 for (;;) { var iteration = await async_iterator.next(); if (iteration.done) { return iteration.value; } else { console.log(iteration.value); } } 

An Iterator<Promise<T>> creates synchronous iterations whose values ​​are Promises. It can be used as follows:

 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 from the future:

 var iterator = await promise_iterator; for (;;) { var iteration = iterator.next(); if (iteration.done) { return iteration.value; } else { console.log(iteration.value); } } 

So Iterator<Promise<T>> and Promise<Iterator<T>> not suitable. Asynchronous generators currently return AsyncIterator instead:

 interface AsyncIterator<T> { Promise<Iteration<T>> next(); } 

Which makes perfect sense. Going to the next element of the iterator is an asynchronous operation, and it can be used exactly as we wanted.

How to use Async generators?

Babeljs.io is already compiling 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 the {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 suggestion for a convenient for await loop for await asynchronous iterators (described in Asynchronous iteration ):

 for await (let line of readLines(filePath)) { print(line); } 

Update:

Unfortunately, async-await did not become part of ECMAScript 2016 . At least await mentions a reserved word for future use.

Update:

Similar offers:

+5
source

Just think: Iterator functions have no return value, so it makes no sense to make them asynchronous. Then there is this conceptual gap between the two approaches. - Iterators are pulled: you call the iterator and call the calculation of the new value - Promises are push-based: Promise pushes the result to the listener. (one or more times)

And although in some cases it would be advisable to create an Iterator<Pomise<Item>>

 function* f(g){ for(...){ let y = await g(); yield y; } } 

I can not think of a single case when it would be advisable to wrap the Iterator in a promise. since there is nothing asynchronous to expose the Iterator from its definition.

0
source

Source: https://habr.com/ru/post/1240234/


All Articles