ブラウザとノードのイベントループの違い
4633 ワード
イベントループは、jsではありふれた話題ですが、ブラウザとノードではイベントループの実行メカニズムが異なり、ブラウザのイベントループはHTML 5で定義された仕様ですが、ノードではlibuvライブラリで実現され、混同してはいけません.
まず、簡単なイベントループペンの問題を見てみましょう.
異なる環境では、出力の結果も異なります.ブラウザからの出力: ノード環境での出力:
次に、ブラウザとノードの時間サイクルの違いを見てみましょう.
1.タスクキュー
ブラウザ環境
ブラウザ環境での非同期タスクは、マクロタスク(macroTask)とマイクロタスク(microTask)に分けられます.マクロタスク(macroTask):script中コード、settimeout、setInterval、I/O、UI render; マイクロタスク(microTask):Promise、Object.observe、MutationObserver.
実行条件が満たされると、マクロタスク(macroTask)とマイクロタスク(microTask)はそれぞれ対応するキューに入れられる:マクロキュー(Macrotask Queue)とマイクロキュー(Microtask Queue)で実行を待つ.
ノード環境
Node環境では、ブラウザ環境よりもタスクタイプが複雑です.microTask:マイクロタスク; nextTick: timers:条件を満たすsettimout、setIntervalコールバックを実行する; I/O callbacks:完了したI/O操作のコールバック関数があるか、前輪からのpollが残っているか. poll:まだ完了していないI/Oイベントを待ち、timersやタイムアウト時間などで待機を終了する; check:setImmediateのコールバックを実行する; close callbacks:すべてのclosing handlesを閉じ、いくつかのoncloseイベント; idle/prepareなど:無視できます.
これにより、イベントループを実行するための対応するタスクキューTimers Queue、I/O Queue、Check Queue、Close Queueが生成される.
2.プロセスの実行
ブラウザ環境
まず メイン スレッドのタスクを する.
Microstask Queueからタスク をクリアするまで り す.
Macrotask Queueの1つを り して する.
2と3を り す.
の に してください.ブラウザページでは スレッドにコードがないと えられ、それぞれ MicroTaskが され けている はmicroTask、「カード 」macroTaskを し ける. のバージョンではブラウザの が と しない があり、 に しないかjsとhtmlの の と している がある. Promiseの ブラウザ APIはリストされていない.
ノード
ループの
のループに る に、 の を います. タスク; を す; タイマーの ;
ループの
ループ のアクション:カレントサイクル のTimers Queueをクリアし、NextTick Queueをクリアし、Microstask Queueをクリアする. カレントサイクル のI/O Queueをクリアし、Nexttick Queueをクリアし、Microstask Queueをクリアする. カレントサイクル のCheck Queueをクリアし、Nexttick Queueをクリアし、Microstask Queueをクリアする. カレントサイクル のClose Queueをクリアし、Nexttick Queueをクリアし、Microstask Queueをクリアする. に る.
nextTick はPromiseなどのmicroTaskより く、
に
プロセス で、 の に してください.timersフェーズ に された
まとめ
ブラウザとノードでのイベントループの いは されやすく、 は のように されています.
ブラウザ :
ノード :
にははっきりしていると いますが、 か があれば で することができます.
の の は のとおりです.https://segmentfault.com/a/1190000013660033?utm_source=channel-hottest
まず、簡単なイベントループペンの問題を見てみましょう.
function sleep(time) {
let startTime = new Date();
while (new Date() - startTime < time) {}
console.log('');
}
setTimeout(() => {
console.log('timeout1');
setTimeout(() => {
console.log('timeout3');
sleep(1000);
});
new Promise((resolve) => {
console.log('timeout1_promise');
resolve();
}).then(() => {
console.log('timeout1_then');
});
sleep(1000);
});
setTimeout(() => {
console.log('timeout2');
setTimeout(() => {
console.log('timeout4');
sleep(1000);
});
new Promise((resolve) => {
console.log('timeout2_promise');
resolve();
}).then(() => {
console.log('timeout2_then');
});
sleep(1000);
});
異なる環境では、出力の結果も異なります.
timeout1
timeout1_promise
timeout1_then
timeout2
timeout2_promise
timeout2_then
timeout3
timeout4
timeout1
timeout1_promise
timeout2
timeout2_promise
timeout1_then
timeout2_then
timeout3
timeout4
次に、ブラウザとノードの時間サイクルの違いを見てみましょう.
1.タスクキュー
ブラウザ環境
ブラウザ環境での非同期タスクは、マクロタスク(macroTask)とマイクロタスク(microTask)に分けられます.
実行条件が満たされると、マクロタスク(macroTask)とマイクロタスク(microTask)はそれぞれ対応するキューに入れられる:マクロキュー(Macrotask Queue)とマイクロキュー(Microtask Queue)で実行を待つ.
ノード環境
Node環境では、ブラウザ環境よりもタスクタイプが複雑です.
process.nextTick
; これにより、イベントループを実行するための対応するタスクキューTimers Queue、I/O Queue、Check Queue、Close Queueが生成される.
2.プロセスの実行
ブラウザ環境
まず
の タスクを し、その すべてのマイクロタスク、1つのマクロタスク、すべてのマイクロタスク、1つのマクロタスク......の に してください.
のコードは したtaskであり、 の
で したmicroTaskを してから の
の コードを する.then
とcatch
こそmicroTaskで、それ の コードは います;ノード
ループの
のループに る に、 の を います.
process.nextTick()
.ループの
ループ のアクション:
nextTick はPromiseなどのmicroTaskより く、
setTimeout
およびsetInterval
setImmediate
より いことがわかる.に
プロセス で、 の に してください.
setImmediate
このラウンドのcheckフェーズで され、timersフェーズで された setTimeout
timersが り されたため、 のラウンドに み、checkフェーズ timersタスクは じである.setTimeout
setImmediate
いがsetTimeout(fn,0)
の の が に0 になることは であるため、 に したsetTimeout(fn,0)
に べてsetImmediate
のコールバック に する がある.まとめ
ブラウザとノードでのイベントループの いは されやすく、 は のように されています.
ブラウザ :
while (true) {
.shift();
();
}
ノード :
while (true) {
loop.forEach(( ) => {
();
nextTick ();
microTask ();
});
loop = loop.next;
}
にははっきりしていると いますが、 か があれば で することができます.
の の は のとおりです.https://segmentfault.com/a/1190000013660033?utm_source=channel-hottest