node.js事件佇列有6個階段:1、「timers」階段;2、「I/O callbacks」階段;3、「idle, prepare」階段;4、「poll」階段;5 、「check」階段;6、「close callbacks」階段。
本教學操作環境:windows7系統、nodejs 12.19.0版,DELL G3電腦。
Node裡的事件佇列和瀏覽器中的差異性還是比較大的,但是共同點就是巨集任務和微任務的機制,是一樣的,如圖是關於node的巨集任務與微任務分類。
nexttick會在node的每一次事件開啟時最先執行(微任務最高優先權)。
而關於node事件佇列可分為如下6個階段:
#1、timers 階段:這個階段執行timer(setTimeout、setInterval )的回呼
2、I/O callbacks 階段:執行一些系統呼叫錯誤,例如網路通訊的錯誤回呼
3、idle, prepare 階段:僅在node內部使用
4、poll 階段:取得新的I/O事件, 適當的條件下node將阻塞在這裡
5、check 階段:執行setImmediate() 的回呼
#6、close callbacks 階段:執行socket 的close 事件回呼
我們重點看timers、poll、check這3個階段就好,因為日常開發中的絕大部分異步任務都是在這3個階段處理的。
timers 階段
timers 是事件循環的第一個階段,Node 會去檢查有無已過期的timer,如果有則把它的回調壓在進入timer的任務佇列中等待執行,事實上,Node 並不能保證timer在預設時間到了就會立即執行,因為Node對timer的過期檢查不一定可靠,它會受機器上其它運行程序影響,或者那個時間點主線程不空閒。例如下面的程式碼,setTimeout() 和 setImmediate() 的執行順序是不確定的。
setTimeout(() => { console.log('timeout')}, 0)setImmediate(() => { console.log('immediate')})
如上段程式碼是個大坑,node無法確定每次事件佇列建立完畢的具體時間,可能這次是5ms(timer被壓入棧,在第二輪才會執行),下次是1ms(timer在第一輪就被捕獲執行了)。因此輸出結果順序不確定,這也是具體原因,而當嵌套一個非同步的操作把他們包裹起來,就會100%保證immediate先執行。
fs.readFile('./index.html',(err,result)=>{ setTimeout(() => { console.log('timeout') }, 0) setImmediate(() => { console.log('immediate') })})
這是因為由於在第一輪未捕捉在timer,所以直接到了poll階段進行io的回調捕捉,當io結束後進入check階段,就會執行immediate,而timeout會在第二輪最開始的timer執行。
poll 階段
poll 階段主要有2個功能:
1.處理poll 佇列的事件
2.當有已逾時的timer,執行它的回呼函數
even loop將同步執行poll隊列裡的回調,直到隊列為空或執行的回調達到系統上限(上限具體多少未詳),接下來even loop會去檢查有無預設的setImmediate(),分兩種情況:
1.若有預設的setImmediate(), event loop將結束poll階段進入check階段,並執行check階段的任務佇列
2.若沒有預設的setImmediate(),event loop會阻塞在該階段等待
注意一個細節,沒有setImmediate()會導致event loop阻塞在poll階段,這樣之前設定的timer豈不是執行不了了?所以咧,在poll階段event loop會有一個檢查機制,檢查timer隊列是否為空,如果timer隊列非空,event loop就開始下一輪事件循環,即重新進入到timer階段。
check 階段
setImmediate()的回呼會被加入check佇列中, 從event loop的階段圖可以知道,check階段的執行順序在poll階段之後。
小結
node中每一輪大的事件循環中劃分出了六個場景,每個場景需要依序執行,比瀏覽器會更加細化,並且在每個階段都會進行巨集任務和微任務的處理,這是比較特殊的一點。
1、Node.js 的事件迴圈分為6個階段
2、瀏覽器和Node 環境下,microtask 任務佇列的執行時機不同
Node.js中,microtask 在事件循環的各個階段之間執行
瀏覽器端,microtask 在事件循環的macrotask 執行完之後執行
3、遞歸的呼叫process .nextTick()會導致I/O starving,官方推薦使用setImmediate()
4、每個事件階段nexttick在微任務中的優先順序是最高的。
更多node相關知識,請造訪:nodejs 教學! !
以上是node.js事件隊列有幾個階段的詳細內容。更多資訊請關注PHP中文網其他相關文章!