【新手向】Node.js事件循環中的:Macrotask 與 Microtask

在Node學習過程當中,不可避免的須要對事件循環機制作深刻理解,其中Macrotask(大型任務)和Microtask(小型任務)比較使人困惑,在一番google以後,我發現了幾篇資料能比較好地解釋他們的原理。所以在這裏彙總+搬運一下。html

一句話解釋

在Nodejs事件循環機制中,有任務兩個隊列:Macrotask隊列和Microtask隊列。在一個事件循環裏,這兩個隊列會分兩步執行,第一步會固定地執行一個(且僅一個)Macrotask任務,第二步會執行整個Microtask隊列中的全部任務。而且,在執行Microtask隊列任務的時候,也容許加入新的Microtask任務,直到全部Microtask任務所有執行完畢,纔會結束循環。node

Macrotasks通常包括: setTimeout, setInterval, setImmediate, I/O, UI rendering;
Microtasks通常包括: process.nextTick, Promises, Object.observe, MutationObserver異步

事件循環機制詳解

從一個事件循環開始,到結束會經歷如下步驟:函數

  1. 檢查Macrotask隊列,選擇其中最先加入(即最老的)的任務X,設置爲「目前運行的任務」。若是任務X不存在,那麼直接跳到步驟4。oop

  2. 運行任務X,即運行對應的回調函數。學習

  3. 設置「目前運行的任務」爲null,從Macrotask隊列中移除任務X。google

  4. 檢查Microtask隊列:code

    1)選擇其中最老的任務a,若是任務a不存在,直接結束Microtask隊列。
    2)設置任務a爲「目前運行的任務」,並執行。
    3)設置「目前運行的任務」爲null,從Microtask隊列中移除任務a。
    4)選擇下一個最老的任務b,跳到步驟2)。
    5)直到隊列裏沒有剩餘的任務,結束隊列。
  5. 跳回步驟1,檢查下一個Macrotask任務。server

關於事件循環步驟,參考文檔中的《理解 Node.js 事件循環》這篇文章講的很是好也很是詳細,強烈推薦想了解的同窗必定要看。htm

如何選用Macrotask或Microtask呢?

能夠這樣簡單理解:若是你想讓一個任務當即執行,那麼就把它設置爲Microtask,除此以外都用Macrotask比較好。由於能夠看出,雖然Node是異步非阻塞的,但在一個事件循環中,Microtask的執行方式基本上就是用同步的。

可能存在的問題

相信讀到這裏你已經意識到,若是一個Microtask隊列太長,或者執行過程當中不斷加入新的Microtask任務,會致使下一個Macrotask任務好久都執行不了。結果就是,你可能會遇到UI一直刷新不了,或者I/O任務一直完成不了。

應該是考慮到了這一點,至少Microtask任務中的process.nextTick任務,是被設置了(在一個事件循環中的)最大調用次數的,叫process.maxTickDepth。默認是1000。必定程度上避免了上述狀況。

參考材料

理解 Node.js 事件循環
Difference between microtask and macrotask within an event loop context

相關文章
相關標籤/搜索