-
磚
setTimeout(() => console.log(1)); setImmediate(() => console.log(2)); process.nextTick(() => console.log(3)); Promise.resolve().then(() => console.log(4)); (() => console.log(5))(); 複製程式碼
執行結果:
5 3 4 1 2 複製程式碼
node事件分 同步、非同步,由於JS的單執行緒原理,非同步事件的處理方式依靠 事件迴圈。
- 非同步事件分為:微事件/巨集事件
- 微事件包括:
- process.nextTick
- Promise.then
- 巨集事件包括:
- setTimeout/setInterval
- setImmediate
- I/O callback
不同的非同步事件,迴圈規則也不同。
巨集事件迴圈
- timers階段:setTimeout/setInterval的回撥函式執行階段
- I/O callbacks階段:未解決的回撥執行執行
- poll階段:輪詢階段。接受新的I/O回撥,並將其加入輪詢列隊中進行先進先出的順序執行。
- 若該階段事件列隊為空,檢查
check
階段是否有事件列隊,有則順序執行。同時也會檢查是否有定時器到達閾值,如果有則迴圈繞到timers
階段時執行。如果沒有其他非同步任務要處理會一直停留在該階段等待 I/O 結果返回。 - 若該階段的事件列隊不為空,則將事件列隊中的事件執行完直到為空,或直到記憶體溢位
- 若該階段事件列隊為空,檢查
- check階段:執行setImmediate()的回撥函式
- close callbacks:執行關閉請求的回撥函式
.on('close', callback)
微事件迴圈
- process.nextTick
- Promise.then
在同一次迴圈中process.nextTick總要比Promise.then先執行
迴圈原則
- 只有前一個階段的事件佇列全部清空以後,才會執行下一個階段的事件佇列
- 進入到下一個階段的事件列隊之前,會先執行微事件列隊直到為空。
- 同一次迴圈中,微事件的執行總是優先於巨集事件
事件執行順序:
- 同步事件
- 發出非同步請求
- 規劃定時器生效的時間
- process.nextTick
- Promise.then
- 事件迴圈
圖解
筆者自畫,理解不當之處,敬請糾正,感激不盡
終極挑戰
setTimeout(() => {
process.nextTick(() => {
console.log(1)
process.nextTick(() => console.log(2))
});
console.log(3)
setTimeout(() => { console.log(4)})
setImmediate(() => console.log(5));
});
setTimeout(() => {
process.nextTick(() => console.log(6));
Promise.resolve(7).then(res=>console.log(res))
console.log(8)
});
(() => console.log(9))();
setImmediate(() => console.log(10));
複製程式碼
你答對了嗎?
9
3
8
1
6
2
7
10
5
4
複製程式碼