
宏任務(macro-task)
定義
消息隊列中的任務稱為宏任務。
產生
宿主環境提供的方法是宏任務,例如setTimeout, setInterval。這些都是瀏覽器或者Node環境實現的。
執行
不斷從消息隊列中取出並被事件循環執行。
類型
注意⚠️:
- ✅代表是宏任務
|
瀏覽器 |
Node |
I/O |
✅ |
✅ |
setTimeout |
✅ |
✅ |
setInterval |
✅ |
✅ |
requestAnimationFrame |
✅ |
❌ |
setImmediate |
❌ |
✅ |
- ⚠️:有些地方會列出來UI Rendering,說這個也是宏任務,但根據HTML規范文檔,發現這很顯然是和微任務平行的一個操作步驟
- requestAnimationFrame姑且也算是宏任務吧,requestAnimationFrame在MDN的定義為,下次頁面重繪前所執行的操作,而重繪也是作為宏任務的一個步驟來存在的,且該步驟晚於微任務的執行。
- setImmediate:用於中斷長時間運行的操作並在瀏覽器完成其他操作(例如事件和顯示更新)后立即運行回調函數。
- UI render:一輪事件循環執行結束之后,下輪事件循環執行之前開始進行UI render
微任務
產生原因
在前面我們知道其實瀏覽器的消息循環系統是由消息隊列和事件循環配合實現的,但是后來為何又出現了微任務呢?因為消息隊列中這種粗時間顆粒度的任務已經不能勝任部分領域的需求,所以又出現了一種新的技術——微任務。微任務可以在實時性和效率之間做一個有效的權衡。通常我們把消息隊列中的任務稱為宏任務,每個宏任務中都包含了一個微任務隊列。
產生
由js引擎自身提供的是微任務,例如Promise。基本上平時接觸到的除了Promise都是宏任務
執行
每個宏任務都有一個微任務隊列,在宏任務結束前會執行微任務里面的任務。
在當前宏任務中的 JavaScript 快執行完成時,也就在 JavaScript 引擎准備退出全局執行上下文並清空調用棧的時候,JavaScript 引擎會檢查全局執行上下文中的微任務隊列,然后按照順序執行隊列中的微任務。WHATWG 把執行微任務的時間點稱為檢查點。
如果在執行微任務的過程中,產生了新的微任務,同樣會將該微任務添加到微任務隊列中,V8 引擎一直循環執行微任務隊列中的任務,直到隊列為空才算執行結束。也就是說在執行微任務過程中產生的新的微任務並不會推遲到下個宏任務中執行,而是在當前的宏任務中繼續執行。
類別
|
瀏覽器 |
Node |
Promise.then catch finally |
✅ |
✅ |
MutationObserver |
✅ |
❌ |
process.nextTick |
❌ |
✅ |
MutationObserver: 提供了監視對DOM樹所做更改的能力,創建並返回一個新的 MutationObserver 它會在指定的DOM發生變化時被調用。
process.nextTick:定義出一個動作,並且讓這個動作在下一個事件輪詢的時間點上執行
宏任務微任務執行圖
參考:
瀏覽器工作原理與實踐