淺析 JS 事件循環之 Microtask 和 Macrotask

簡介

咱們在上一篇 《淺析 JS 中的EventLoop 事件循環》 中提到一個 Event Queue,其實在事件循環中 queue 一共有兩種,還有一種叫 Job Queuehtml

其中git

Event Queue 在 HTML 規範中被稱爲 Task Queue,可是爲了區分,通常都叫做 Macrotask Queue
Job Queue 是在 ECMAScript 規範中談及處理 Promise 回調時提到的,可是因爲和 V8 中的實現比較類似,因此通常都稱爲 Microtask Queue

Macrotask

Macrotasks 包含了解析 HTML、生成 DOM、執行主線程 JS 代碼和其餘事件如 頁面加載、輸入、網絡事件、定時器事件等。從瀏覽器的角度,Macrotask 表明的是一些離散的獨立的工做。github

常見應用
setTimeout, setInterval, setImmediate, requestAnimationFrame, I/O, UI renderingweb

Microtask

Microtasks 則是爲了完成一些更新應用程序狀態的較小的任務,如處理 Promise 的回調和 DOM 的修改,以便讓這些任務在瀏覽器從新渲染以前執行。Microtask 應該以異步的方式儘快執行,因此它們的開銷比 Macrotask 要小,而且可使咱們在 UI 從新渲染以前執行,避免了沒必要要的 UI 渲染。api

常見應用
process.nextTick, Promises, Object.observe, MutationObserverpromise

執行順序

Event Loop 的實現須要至少一個 Macrotask Queue 和至少一個 Microtask Queue。爲了便於理解,咱們都簡化成一個。
簡單來講,Microtask Queue 具備更高的優先級,即執行一個 Macrotask 任務後,就會清空整個 Microtask Queue,此時若是有新的 Microtask 加入也會被執行。瀏覽器

因此咱們來看下面的代碼:
圖片描述網絡

執行順序是什麼?
咱們已經知道 setTimeout 是 Macrotask,Promise 是 Microtask,而這段代碼從上到下執行也是一個 Macrotaskapp

步驟:webapp

  1. 開始執行,執行腳本做爲一個任務進入 Macrotask Queue,同時進入調用棧執行
  2. Line 1, 輸出 script start
  3. Line 3 的 setTimeout 回調進入 Macrotask Queue 等待
  4. Line 7 的回調進入 Microtask Queue 等待
  5. Line 13 輸出 script end,此時腳本執行完成(即完成了一個 Macrotask)
  6. 開始執行 Microtask Queue,從中拿出一個放入調用棧執行
  7. 開始執行 Line 7 的回調,該回調輸出 promise1,返回 undefined
  8. Line 9 的回調進入 Microtask Queue,因爲 Microtask Queue 沒有清空,直接執行該回調,輸出 promise2,該回調返回 undefined
  9. Microtask Queue 已清空(此時瀏覽器能夠更新渲染UI),開始將 Macrotask Queue 中任務放入調用棧執行
  10. 執行 Line 3 的回調,輸出 setTimeout,Macrotask Queue 清空
  11. 程序執行完成

因此打印順序爲:

script start -> script end -> promise1 -> promise2 -> setTimeout

PS. 上面的這段代碼執行流程,建議看原文的倒數第二篇參考文章,有動態交互操做能夠演練。

總結

microtask-macrotask.png

  1. Microtask 相比 Macrotask 具備更高的優先級
  2. Macrotask 老是在 JS 代碼執行完成而且 Microtask Queue 清空以後執行
  3. JS 代碼執行自己也是一個 Macrotask
  4. Microtask Queue 清空後有可能會從新渲染 UI
  5. Promise 屬於 Microtask,setTimeout 屬於 Macrotask

整體的執行順序爲:常規代碼 -> promises -> events 和 setTimeout 等

參考文章

原文連接
ECMA262 Job Queues
HTML Standard Task Queue
HTML系列:macrotask和microtask
microtask and macrotask a hands on approach
difference-between-microtask-and-macrotask-within-an-event-loop-context

公衆號:碼力全開
bVbrEUH?w=258&h=258

相關文章
相關標籤/搜索