事件迴圈(event loop)

鬧鬧不愛鬧發表於2018-12-26

node環境

nodejs中的事件迴圈依賴六個階段,每個階段對應一種型別的事件,並且繫結一個事件佇列。每次事件迴圈進入每個階段,都會從對應的佇列中取出事件進行執行,直到此次事件迴圈的事件佇列為空或者執行該階段的事件達到系統最大數量,然後進入下個階段。

timer: 執行到期的setTimeOut和setInterval回撥。

I/O: 執行上次迴圈中遺留的(在poll階段推遲執行)i/o回撥。

idle, prepare: node內部事件執行。

poll: 這是個觀察的階段,包括檔案讀取,網路請求等等,如果有對應的回撥可以執行,則執行,直到時間耗盡或者達到系統最大數量為止(進入下一階段)。如果沒有對應的回撥可以執行,則在一段時間內會持續監聽(阻塞)。這個阻塞時間是按照以下規則來確定的:首先,如果此時check階段,close階段,I/O階段有任務可以執行,則設定阻塞時間為零(立即進入下一階段);否則取最近的定時器執行,如果最近的定時器到期,則立即執行該定時器回撥;如果沒有定時器任務需要執行,則一直阻塞在poll階段。

check: 執行setImmediate註冊的回撥。

close:執行close事件註冊的回撥。

nextTickQueue和microTaskQueue: 這兩種事件在從當前階段執行完畢,進入下次階段之前執行,和其他型別的事件不同的是,其他事件都有對應的系統最大數量,而這兩種型別的事件沒有系統依賴的最大限制,node會一直執行它們的佇列,直到佇列為空(可能造成死迴圈)。而且nextTick的優先順序大於microTask。

瀏覽器環境

瀏覽器環境的事件迴圈依賴兩個事件佇列,一個是巨集任務的事件佇列(由事件觸發執行緒維護),一個是微任務的事件佇列(由js引擎執行緒維護)。

1. 將當前執行上下文壓入執行呼叫棧(js執行緒),js呼叫棧執行當前的同步任務。遇到非同步任務,巨集任務由對應的其他執行緒接管(事件觸發執行緒,定時器執行緒,http請求執行緒),當這些執行緒處理完這些任務後,將回撥新增到事件佇列(event queue)隊尾;微任務直接新增到微任務的事件佇列中。當此次evet loop結束後(執行棧為空),會檢視微任務佇列中是否有任務等待執行,有的話將任務全部依次執行。執行完微任務後,從event queue佇列首部取出一個回撥壓入執行棧進行執行。依次類推。


參考連結

1. www.zcfy.cc/article/nod…

2. juejin.im/post/5b0ab7…


相關文章