一個事件循環(event loop)中會有一個正在執行的任務(task),這個任務就是從 macrotask 中來的。當該 macrotask 執行結束後,所有可用的 microtask 將會在同一個事件循環中執行,當這些 microtask 執行結束後還能繼續添加 microtask 直至整個 microtask 隊列執行結束。
當我們想以同步的方式處理異步任務時就用 microtask(比如需要直接在某斷代碼後去執行某個任務,正如 Promise)。其他情況就直接用 macrotask。
setTimeout
、setInterval
、I/O、UI 渲染process.nextTick
、Object.observe
、MutationObserver根據 WHATWG 規範:
當 call stack 為空時,開始依次執行:
執行 microtask queue
上面是一個簡單的 event loop 執行模型。再簡單點可總結為:
當一個 macrotask 正處執行狀態,亦可能會有新的事件被註冊(創建新 task)。比如:
promiseA.then()
的回調就是一個 task
promiseA
是 resolved 或 rejected,則該 task 會放入當前事件循環回合的 microtask queuepromiseA
是 pending,則該 task 會放入事件循環的未來某個回合的 microtask queuesetTimeout
的回調也是 task,它會被放入 macrotask queue(即使是 0ms)setTimeout
的回調都是 task,包裹在一個 <script>
標籤中的 JS 代碼亦是一個 task——它們都是 macrotask。完 :)