ジェネレーターは、 anIterator
と anの 2 つの組み合わせですObserver
。
イテレータ
イテレータは、呼び出されたときに反復可能なものである iterable を返すものです。ES6 以降、すべてのコレクション (Array、Map、Set、WeakMap、WeakSet) は Iterable コントラクトに準拠しています。
ジェネレーター(イテレーター)はプロデューサーです。反復では、消費者PULL
は生産者からの値です。
例:
function *gen() { yield 5; yield 6; }
let a = gen();
を呼び出すたびにa.next()
、基本的pull
にイテレータからの値とpause
での実行を行っていyield
ます。次に を呼び出すとa.next()
、以前に一時停止した状態から実行が再開されます。
観察者
ジェネレーターはオブザーバーでもあり、これを使用していくつかの値をジェネレーターに送り返すことができます。例を挙げてよりよく説明しました。
function *gen() {
document.write('<br>observer:', yield 1);
}
var a = gen();
var i = a.next();
while(!i.done) {
document.write('<br>iterator:', i.value);
i = a.next(100);
}
yield 1
ここでは、 が何らかの値に評価される式のように使用されていることがわかります。評価される値は、a.next
関数呼び出しに引数として送信される値です。
したがって、最初に生成されi.value
た最初の値 ( 1
) になり、次の状態への反復を続行するときに、 を使用してジェネレーターに値を送り返しますa.next(100)
。
これは Node.JS のどこで使用できますか?
spawn
ジェネレーターは(taskJS または co の) 関数と共に広く使用されており、この関数はジェネレーターを取り込み、非同期コードを同期的に記述できるようにします。これは、非同期コードが同期コードに変換されたり、同期的に実行されたりするという意味ではありません。のように見えるコードを書くことができることを意味しますsync
が、内部的にはまだasync
です。
同期がブロックされています。非同期は待機中です。ブロックするコードを書くのは簡単です。PULL すると、割り当て位置に値が表示されます。PUSHするとコールバックの引数位置に値が現れる
イテレータを使用するとPULL
、プロデューサーから値が取得されます。コールバックを使用すると、プロデューサーPUSH
は値をコールバックの引数位置に渡します。
var i = a.next() // PULL
dosomething(..., v => {...}) // PUSH
ここでは、コールバックから値を取得a.next()
し、2 番目にコールバック関数の引数位置に値を入力します。v => {...}
PUSH
v
このプル/プッシュ メカニズムを使用して、次のような非同期プログラミングを記述できます。
let delay = t => new Promise(r => setTimeout(r, t));
spawn(function*() {
// wait for 100 ms and send 1
let x = yield delay(100).then(() => 1);
console.log(x); // 1
// wait for 100 ms and send 2
let y = yield delay(100).then(() => 2);
console.log(y); // 2
});
したがって、上記のコードを見ると、blocking
(yield ステートメントが 100 ミリ秒待機してから実行を継続する) ように見える非同期コードを書いていますが、実際にはwaiting
. generatorのpause
andresume
プロパティにより、この驚くべきトリックを実行できます。
それはどのように機能しますか?
spawn 関数はyield promise
、ジェネレーターから promise の状態を PULL するために使用し、promise が解決されるまで待機し、解決された値をジェネレーターに PUSH して、それを消費できるようにします。
今すぐ使う
したがって、ジェネレーターと spawn 関数を使用すると、NodeJS のすべての非同期コードをクリーンアップして、同期しているように見えるようにすることができます。これにより、デバッグが容易になります。コードもスッキリ見えます。
ところで、これは ES2017 用にネイティブに JavaScript に導入されます - as async...await
. ただし、ライブラリで定義されている spawn 関数 (taskjs、co、または bluebird) を使用して、ES2015/ES6 および ES2016 で現在それらを使用できます。