首頁 > web前端 > 前端問答 > node.js事件隊列有幾個階段

node.js事件隊列有幾個階段

青灯夜游
發布: 2021-12-09 17:55:15
原創
2271 人瀏覽過

node.js事件佇列有6個階段:1、「timers」階段;2、「I/O callbacks」階段;3、「idle, prepare」階段;4、「poll」階段;5 、「check」階段;6、「close callbacks」階段。

node.js事件隊列有幾個階段

本教學操作環境:windows7系統、nodejs 12.19.0版,DELL G3電腦。

Node裡的事件佇列和瀏覽器中的差異性還是比較大的,但是共同點就是巨集任務和微任務的機制,是一樣的,如圖是關於node的巨集任務與微任務分類。
node.js事件隊列有幾個階段
nexttick會在node的每一次事件開啟時最先執行(微任務最高優先權)。

而關於node事件佇列可分為如下6個階段:
node.js事件隊列有幾個階段

#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中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板