咱們在上一篇 《淺析 JS 中的EventLoop 事件循環》 中提到一個 Event Queue
,其實在事件循環中 queue 一共有兩種,還有一種叫 Job Queue
html
其中git
Event Queue
在 HTML 規範中被稱爲Task Queue
,可是爲了區分,通常都叫做Macrotask Queue
Job Queue
是在 ECMAScript 規範中談及處理 Promise 回調時提到的,可是因爲和 V8 中的實現比較類似,因此通常都稱爲Microtask Queue
Macrotasks 包含了解析 HTML、生成 DOM、執行主線程 JS 代碼和其餘事件如 頁面加載、輸入、網絡事件、定時器事件等。從瀏覽器的角度,Macrotask 表明的是一些離散的獨立的工做。github
常見應用setTimeout
, setInterval
, setImmediate
, requestAnimationFrame
, I/O
, UI rendering
web
Microtasks 則是爲了完成一些更新應用程序狀態的較小的任務,如處理 Promise 的回調和 DOM 的修改,以便讓這些任務在瀏覽器從新渲染以前執行。Microtask 應該以異步的方式儘快執行,因此它們的開銷比 Macrotask 要小,而且可使咱們在 UI 從新渲染以前執行,避免了沒必要要的 UI 渲染。api
常見應用process.nextTick
, Promises
, Object.observe
, MutationObserver
promise
Event Loop 的實現須要至少一個 Macrotask Queue 和至少一個 Microtask Queue。爲了便於理解,咱們都簡化成一個。
簡單來講,Microtask Queue 具備更高的優先級,即執行一個 Macrotask 任務後,就會清空整個 Microtask Queue,此時若是有新的 Microtask 加入也會被執行。瀏覽器
因此咱們來看下面的代碼:
網絡
執行順序是什麼?
咱們已經知道 setTimeout 是 Macrotask,Promise 是 Microtask,而這段代碼從上到下執行也是一個 Macrotaskapp
步驟:webapp
script start
script end
,此時腳本執行完成(即完成了一個 Macrotask)promise1
,返回 undefinedpromise2
,該回調返回 undefinedsetTimeout
,Macrotask Queue 清空因此打印順序爲:
script start -> script end -> promise1 -> promise2 -> setTimeout
PS. 上面的這段代碼執行流程,建議看原文的倒數第二篇參考文章,有動態交互操做能夠演練。
整體的執行順序爲:常規代碼
-> 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
公衆號:碼力全開