js 和 node 裡面的事件迴圈

2022-06-22 21:48:13 字數 1868 閱讀 8778

前言:之前有接觸過 js 事件迴圈,感覺比較容易理解。後面學習《深入淺出node.js》的時候,發現裡面提到的事件迴圈有點繞比較難理解,後面查了一些資料和部落格後,發現 node 環境下的事件迴圈和我之前接觸的事件迴圈是有一定的區別的。

廢話不多說,先上圖:

js 的事件迴圈,把非同步任務分為兩種:巨集任務 (macrotask) 和微任務 (microtask)。對應也有兩個佇列來儲存這些任務**函式:巨集任務佇列和微任務佇列。

在一次 tick(迴圈)裡面,流程大概如下:

1. 如果巨集任務佇列不為空,從巨集任務取出乙個巨集任務執行。

2. 如果微任務佇列不為空,把微任務佇列的全部微任務都執行了。

3. 然後如果 dom 需要更新,就對 dom 進行更新渲染。

在具體了解 node 是事件迴圈流程之前,我們先來看看 node 是如何處理非同步任務的:

對於非同步任務,node 做一種劃分:i/o 和 非i/o。i/o 非同步任務就扔給特定的執行緒池去處理,非 i/o 就自己來處理。(這就是為什麼 node 適合搭建 i/o 密集型伺服器而不適合 cpu 密集型伺服器)。

而不管怎麼處理,處理完了之後都會把**函式註冊成事件放入事件佇列(這一步依賴事件對應的觀察者),等待事件迴圈來處理。

拓展:node 下的多執行緒和單執行緒:事件迴圈對**函式的邏輯處理當然還是 js 單執行緒。

不過多執行緒依舊是 node 事件迴圈的基礎。

在上圖可以看到,對於非同步i/o,node 不是直接處理的,而且扔給了 i/o 執行緒池來處理。(這個 i/o 執行緒池的具體實現在不同平台也不同,不過本質都是用執行緒池的多執行緒來處理,所以從 libuv 層面可以理解為就是乙個 i/o 執行緒池來處理)

在大概了解了 node 的非同步 i/o 模型後,我們再來看看 node 事件迴圈裡一次 tick 的具體流程,了解這個,我們才能知道 node 事件迴圈和 js 事件迴圈對於**執行順序的控制究竟有什麼不同。

廢話不多說,上圖:

是不是看著很亂,一共有6個階段。但其實我們正常開發一般只會涉及到 3 個階段:

1. timer 階段:處理 settimeout 和 setinterval 的**

2. poll 階段:處理非同步 i/o 完成後的**

3. check 階段:處理 setimmediate 的**

node 事件迴圈 6 個階段處理的事件,都有乙個先入先出的事件佇列來進行儲存。每一次 tick 的時候,會按照上圖的階段順序去處理這 6 個階段的事件佇列的全部事件**函式。(和 js 一次tick 處理乙個巨集任務不同)

那麼,微任務佇列呢?node 裡面的微任務大概有兩種:

1. process.nexttick **

2. resolve 的 promise **

node 依舊是一次性將微任務佇列裡的微任務全部處理。而發生的時機,大部分是在事件迴圈的 6 個事件處理階段之後。(js 事件迴圈則是執行完巨集任務之後)

為什麼說大部分階段呢,因為有乙個階段是特殊的,就是 poll 輪詢階段。它特殊在清空微任務佇列的時機:它是執行完畢 poll 佇列裡面的乙個**函式後就清空一次微任務佇列。

js裡面for迴圈裡面的of和in區別

for in 語句用於遍歷陣列或者物件的屬性名稱 key 鍵名 陣列中的每個元素的索引被視為屬性名稱,所以在使用for in遍歷array時,拿到的是每個元素索引 for in 迴圈只遍歷可列舉屬性。像 array和 object使用內建建構函式所建立的物件都會繼承自object.prototype...

js 裡面的 和

1.1.1兩邊條件都為true時,結果才為true 1.2如果有乙個為false,結果就為false 1.3當第乙個條件為false時,就不再判斷後面的條件 注意 當數值參與邏輯與運算時,結果為true,那麼會返回的會是第二個為真的值 如果結果為false,返回的會是第乙個為假的值。2.2.1只要有...

node裡面的buffer理解

node提供了專門讀寫檔案的模組,檔案內容都是2進製存放在記憶體中的 node讀取檔案的結果都是16進製制,那麼你要學會進製轉換,二進位制0b開頭 八進位制0開頭,十六進製制0x 基礎知識 1位元組 8bit 乙個漢字 3位元組,在不同的編碼下位元組個數還有不同的 乙個英文 1位元組 buffer裡...