Node.js バージョン 0.10 が本日リリースされ、導入されまし setImmediate
た。APIの変更に関するドキュメントでは、再帰nextTick
呼び出しを行うときに API を使用することが提案されています。
MDN の言うことから、それはprocess.nextTick
.
いつ使用するnextTick
必要がありますsetImmediate
か?
私はこれを非常にうまく説明できると思います。nextTick
は現在の操作の最後に呼び出されるため、再帰的に呼び出すと、イベント ループの続行が妨げられる可能性があります。setImmediate
イベント ループのチェック フェーズで起動することでこれを解決し、イベント ループを正常に続行できるようにします。
┌───────────────────────┐
┌─>│ timers │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ I/O callbacks │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ idle, prepare │
│ └──────────┬────────────┘ ┌───────────────┐
│ ┌──────────┴────────────┐ │ incoming: │
│ │ poll │<─────┤ connections, │
│ └──────────┬────────────┘ │ data, etc. │
│ ┌──────────┴────────────┐ └───────────────┘
│ │ check │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
└──┤ close callbacks │
└───────────────────────┘
ソース: https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/
チェック フェーズはポーリング フェーズの直後であることに注意してください。これは、ポーリング フェーズと I/O コールバックが、呼び出しがsetImmediate
実行される可能性が最も高い場所であるためです。したがって、理想的には、これらの呼び出しのほとんどは実際には非常に即時であり、nextTick
すべての操作の後にチェックされ、技術的にはイベント ループの外に存在するものほど即時ではありません。
setImmediate
との違いの例を少し見てみましょうprocess.nextTick
。
function step(iteration) {
if (iteration === 10) return;
setImmediate(() => {
console.log(`setImmediate iteration: ${iteration}`);
step(iteration + 1); // Recursive call from setImmediate handler.
});
process.nextTick(() => {
console.log(`nextTick iteration: ${iteration}`);
});
}
step(0);
このプログラムを実行したばかりで、イベント ループの最初の反復を実行しているとします。step
反復ゼロで関数を呼び出します。setImmediate
次に、 用と用の 2 つのハンドラを登録しますprocess.nextTick
。setImmediate
次に、次のチェック フェーズで実行されるハンドラーからこの関数を再帰的に呼び出します。ハンドラーはnextTick
、イベント ループを中断する現在の操作の最後に実行されるため、2 番目に登録されていても、実際には最初に実行されます。
最終的な順序は次のとおりです。nextTick
現在の操作が終了すると起動し、次のイベント ループが開始し、通常のイベント ループ フェーズが実行され、起動し、プロセスを最初からやり直すために関数をsetImmediate
再帰的に呼び出します。step
現在の営業終了、nextTick
火災等
上記のコードの出力は次のようになります。
nextTick iteration: 0
setImmediate iteration: 0
nextTick iteration: 1
setImmediate iteration: 1
nextTick iteration: 2
setImmediate iteration: 2
nextTick iteration: 3
setImmediate iteration: 3
nextTick iteration: 4
setImmediate iteration: 4
nextTick iteration: 5
setImmediate iteration: 5
nextTick iteration: 6
setImmediate iteration: 6
nextTick iteration: 7
setImmediate iteration: 7
nextTick iteration: 8
setImmediate iteration: 8
nextTick iteration: 9
setImmediate iteration: 9
step
ではなく、への再帰呼び出しをnextTick
ハンドラに移動しましょうsetImmediate
。
function step(iteration) {
if (iteration === 10) return;
setImmediate(() => {
console.log(`setImmediate iteration: ${iteration}`);
});
process.nextTick(() => {
console.log(`nextTick iteration: ${iteration}`);
step(iteration + 1); // Recursive call from nextTick handler.
});
}
step(0);
再帰呼び出しをハンドラーに移動しstep
たnextTick
ので、別の順序で動作します。イベント ループの最初の繰り返しが実行され、ハンドラーとハンドラーstep
の登録が呼び出されます。現在の操作が終了すると、ハンドラーが起動し、別のハンドラーと別のハンドラーを再帰的に呼び出して登録します。ハンドラーは現在の操作の後に起動するため、ハンドラー内にハンドラーを登録すると、現在のハンドラー操作が終了した直後に 2 番目のハンドラーが実行されます。ハンドラーは起動し続け、現在のイベント ループが継続するのを防ぎます。私たちはすべてを乗り越えますsetImmedaite
nextTick
nextTick
step
setImmediate
nextTick
nextTick
nextTick
nextTick
nextTick
nextTick
単一のsetImmediate
ハンドラーが起動する前に、ハンドラー。
上記のコードの出力は次のようになります。
nextTick iteration: 0
nextTick iteration: 1
nextTick iteration: 2
nextTick iteration: 3
nextTick iteration: 4
nextTick iteration: 5
nextTick iteration: 6
nextTick iteration: 7
nextTick iteration: 8
nextTick iteration: 9
setImmediate iteration: 0
setImmediate iteration: 1
setImmediate iteration: 2
setImmediate iteration: 3
setImmediate iteration: 4
setImmediate iteration: 5
setImmediate iteration: 6
setImmediate iteration: 7
setImmediate iteration: 8
setImmediate iteration: 9
再帰呼び出しを中断せず、10 回の反復後に中止した場合、呼び出しは再帰をnextTick
続け、イベント ループが次のフェーズに進むことはありません。これは、nextTick
再帰的に使用するとブロッキングになる可能性がありますがsetImmediate
、次のイベント ループで発生し、setImmediate
1 つのイベント ループ内から別のハンドラーを設定しても、現在のイベント ループはまったく中断されず、イベント ループのフェーズを通常どおり実行し続けることができます。
それが役立つことを願っています!
nextTick
PS - 2 つの関数の名前は、現在のループの終わりではなく次のイベント ループで起動するように聞こえるため、簡単に交換できるという他のコメンターに同意します。現在のループの終了はより「即時」です。 "次のループの開始より。まあ、それは API が成熟し、人々が既存のインターフェースに依存するようになるにつれて得られるものです。
回答のコメントでは、nextTick がマクロセマンティクスからマイクロセマンティクスに移行したことを明示的に述べていません。
ノード 0.9 より前 (setImmediate が導入されたとき)、nextTick は次の呼び出しスタックの開始時に動作しました。
ノード 0.9 以降、nextTick は既存の呼び出しスタックの最後で動作しますが、setImmediate は次の呼び出しスタックの最初で動作します。
ツールと詳細については、https://github.com/YuzuJS/setImmediateをご覧ください。
簡単に言えば、process.NextTick() はイベント ループの次のティックで実行されます。ただし、setImmediate には基本的に別のフェーズがあり、setImmediate() で登録されたコールバックが IO コールバックおよびポーリング フェーズの後にのみ呼び出されるようにします。
わかりやすい説明については、このリンクを参照してください: https://medium.com/the-node-js-collection/what-you-should-know-to-really-understand-the-node-js-event-loop-and -its-metrics-c4907b19da4c