5

ES6はgenerators that return iteratorsがありますES6非同期発電結果

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

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

Promisesを返す非同期機能のための提案があります:

async function f(x) { 
    let y = await g(x); 
    return y * y; 
} 

f(2).then(y => { 
    console.log(y); 
}); 

私は2つを組み合わせた場合それでは、このように、起こる:

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

何が返されますか?それはPromise<Iterator<Item>>ですか? Iterator<Promise<Item>>?他に何か?どのように私はそれを消費するのですか?次のいずれかにアクセスしようとする前に利用可能になるまで、各項目のを待ち

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

:私は、非同期的にその結果を反復するかを、対応するforループがなければならないようなものを想像してみてください。

+2

うーむ、非同期/ await'提案はまだない 'として、この質問に答えるには早すぎます承認された – thefourtheye

+0

非同期イテレータ - sp cがあります - 私はモバイルになっていますが、ほとんどの場合既に決定されています。それは '次の'が約束を返すジェネレータです。 –

答えて

5

Promise<Iterator<Item>>またはIterator<Promise<Item>>

どちらもありません。まだ承認されていませんが、現在の実装は何か他のものを返します。 Kris Kowalはwritten an about async generators、参考文献はJafar Husain's AsyncGenerator proposal for ES7です。 編集tc39 proposalbabel support

のは、いくつかの種類(単純化)を定義してみましょう:

interface Iterator<T> { 
    Iteration<T> next(); 
} 

type Iteration<T> = { done: boolean, value: T } 

私たちは、このように使用することができます何かを探しています:

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

Iterator<Promise<T>>は、値が約束されている同期反復を生産しています。それはこのように使用することができます:

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

Promise<Iterator<T>>は、将来的に開始し、普通の同期イテレータです:

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

そうもないIterator<Promise<T>>Promise<Iterator<T>>は適していました。完全に理にかなって

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

:現在、非同期発電機ではなくAsyncIterator sを返します。イテレータの次の要素に移動することは非同期操作であり、これは私たちが望むのと全く同じように使用できます。

どのように非同期ジェネレータを消費しますか?

Babeljs.ioは既に非同期ジェネレータをコンパイルします。 Babeljs.io/repl example

EDIT:バベル6、babel-plugin-transform-regenerator{asyncGenerators:true}オプションでそれをサポートしていますので、babeljs.ioにはプリセットは非同期発電機をコンパイルします。

EDITtransform-async-generator-functionsバベル6プラグインを参照してください。

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(); 

Async iterationで説明)非同期イテレータのための便利なfor awaitループのための提案があります:

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

更新:

残念ながら、async-awaitはの一部にはなりませんでしたが、 ECMAScript 2016。少なくともawaitは、将来の使用のための予約語として言及されている。

更新:

関連の提案:

+0

しかし、非同期ジェネレータを「委譲する」方法は? 'yield * await'も' yield await * 'も適合しない。 –

+0

@ polkovnikov.phこの提案では、「イールド*の動作は、非同期イテレータへの委任をサポートするように変更されています。しかし、あなたは正規のジェネレータにどのように委任したらいいのでしょうか?最終的には、forループで常にyieldを使用できます。 –

0

考えてみましょう: Iterator関数には戻り値がないため、非同期にすることは意味がありません。 これらの2つのアプローチの間には、この概念的なギャップがあります。 - イテレータはプルベースです。イテレータを呼び出し、新しい値の計算を呼び出します。 - プロミスはプッシュベースです。プロミスは結果をそのリスナーにプッシュします。 (一回しかない)

そして、それはIterator<Pomise<Item>>

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

を作成するために、いくつかのケースでローミングサービスを作るだろうが、私はそれは約束にイテレータをラップするために理にかなってどのような場合を考えることはできません。イテレータの定義からイテレータをインスタンス化する際に非同期は存在しないためです。

関連する問題