在前端開發中,微任務(Microtasks)和宏任務(Macrotasks)代表了兩種不同的非同步任務型別,它們在事件迴圈(Event Loop)中的執行時機和順序有所不同。理解它們的區別對於編寫高效且行為符合預期的 JavaScript 程式碼至關重要。
宏任務 (Macrotasks):
-
定義: 宏任務是瀏覽器發起的一些非同步任務,它們通常包含:
setTimeout
setInterval
setImmediate
(Node.js 環境)requestAnimationFrame
(瀏覽器動畫)- I/O 操作
- UI 渲染
- 使用者互動事件 (例如:點選、滾動)
-
執行時機: 每一個宏任務執行完畢後,事件迴圈會檢查微任務佇列,並將所有在佇列中的微任務執行完畢,然後再執行下一個宏任務。
微任務 (Microtasks):
-
定義: 微任務是 JavaScript 引擎自身發起的一些非同步任務,它們通常包含:
Promise.then()
、Promise.catch()
、Promise.finally()
queueMicrotask()
MutationObserver
(監聽 DOM 變化)
-
執行時機: 在當前宏任務執行完畢後,立即執行所有在微任務佇列中的微任務,然後再執行下一個宏任務。這意味著在一個宏任務中,如果產生了新的微任務,這些微任務會在下一個宏任務開始之前被執行。
關鍵區別總結:
特性 | 宏任務 (Macrotasks) | 微任務 (Microtasks) |
---|---|---|
發起者 | 瀏覽器或 Node.js 環境 | JavaScript 引擎自身 |
典型示例 | setTimeout , setInterval , I/O , UI rendering |
Promise.then() , queueMicrotask() , MutationObserver |
執行時機 | 每個宏任務之後,執行所有微任務,然後執行下一個宏任務 | 當前宏任務之後,立即執行所有微任務 |
佇列 | 宏任務佇列 | 微任務佇列 |
示例說明:
console.log('Start');
setTimeout(() => {
console.log('setTimeout');
}, 0); // 宏任務
Promise.resolve().then(() => {
console.log('Promise.then');
}); // 微任務
console.log('End');
輸出結果為:
Start
End
Promise.then
setTimeout
解釋:
Start
和End
同步執行並列印。setTimeout
和Promise.then
都是非同步操作,被新增到各自的佇列中。- 儘管
setTimeout
的延遲時間為 0,但它仍然是一個宏任務,會在當前宏任務 (主執行緒的同步程式碼) 執行完畢後才執行。 - 在當前宏任務執行完畢後,事件迴圈會檢查微任務佇列,發現
Promise.then
,於是先執行Promise.then
並列印Promise.then
。 - 最後,事件迴圈取出
setTimeout
這個宏任務並執行,列印setTimeout
。
理解微任務和宏任務的區別對於控制程式碼執行順序、避免競態條件以及編寫高效的非同步程式碼至關重要。 例如,在處理 UI 更新時,使用微任務可以確保在瀏覽器重新渲染之前完成所有必要的 DOM 操作,從而避免閃爍和效能問題。