イベントループ
CoddyのNode.jsジャーニー「Node.jsの基礎」セクションの一部。レッスン 26/33。
コールバックとプロミスは後で実行されるため、正確なタイミングを把握していないとバグが潜みます。
Nodeはまず、すべての同期コードを最後まで実行します。次に、マイクロタスクを実行します。つまり、プロミスのコールバックと、queueMicrotaskに渡された関数です。その後にタイマーが実行されます。setTimeout(fn, ms)は、msミリ秒後にfnを1回実行します。setTimeout(fn, 0)でさえ、マイクロタスクが終わるまで待ちます。
setTimeout(() => console.log('C timer'), 0);
Promise.resolve().then(() => console.log('B promise'));
console.log('A sync');
// A sync, B promise, C timer遅延時間が0というのは、マイクロタスクの後で可能な限りすぐに実行されるという意味であり、マイクロタスクより先に実行されることはありません。タイマーは遅延時間の順に実行されます。遅延時間が同じ場合は、先に設定されたタイマーが先に実行されます。
チャレンジ
簡単Node はコードを決まった順序で実行します。まず通常の行、次に Promise のコールバックなどのマイクロタスク、その後にタイマーが実行されます。この順序を利用して、行を移動せずに、4 行を番号順に出力させましょう。
order.js は、4 行を 4 から 1 の順に出力します。行を移動したり並べ替えたりしないでください。代わりに、3 行をラップして、後で実行されるようにします。
console.log('1 sync')はそのままにします。通常のコードが最初に実行されます。2 microtaskの行をqueueMicrotaskでラップして、通常のコードの直後に実行されるようにします。3 timeoutの行と4 timeout laterの行を、それぞれ個別にsetTimeoutでラップします。setTimeout(fn, ms)は、msミリ秒後に関数fnを 1 回実行します。4 行目は 3 行目より先に設定されるため、より長い遅延が必要です。
node order.js を実行すると、次のように出力されます。
1 sync
2 microtask
3 timeout
4 timeout later試してみましょう: 実行する前に、順序を予想してください。それから「実行」を押すと、ターミナルに $ node order.js と表示されます。次に、両方のタイマーの遅延を 0 にして、もう一度実行します。遅延が同じ場合は、先に設定されたタイマーが先に実行されるため、今度は 4 timeout later が 3 timeout より先に出力されます。「確認」を押す前に、4 行目の遅延を長い値に戻してください。
自分で試してみよう
// これらの行を移動せずに、番号順に出力されるようにしてください。
// 代わりに、それぞれを queueMicrotask と setTimeout で囲んでください。
console.log('4 timeout later');
console.log('3 timeout');
console.log('2 microtask');
console.log('1 sync');
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
Node.jsの基礎のすべてのレッスン
自分で練習してみよう: Expressプレイグラウンド