JavaScript 中的宏任務與微任務
JavaScript 是一種單線程的編程語言,這意味著在同一時間只能執行一個任務。為了有效地處理并發操作,JavaScript 引入了事件循環(Event Loop)機制,其中宏任務(Macro Task)和微任務(Micro Task)在其中扮演著關鍵角色。
1. 什么是宏任務和微任務?
-
宏任務(Macro Task) 是 JavaScript 中執行的大塊任務或代碼塊,它包括了一些常見的操作,如:
setTimeoutsetIntervalsetImmediate(僅在 Node.js 中)- I/O 操作
- UI 渲染
- 事件處理
-
微任務(Micro Task) 是一個需要在當前宏任務完成后、下一個宏任務開始前立即執行的小任務。常見的微任務有:
Promise.then、Promise.catch、Promise.finallyMutationObserverprocess.nextTick(僅在 Node.js 中)
2. 事件循環與任務隊列
JavaScript 的事件循環決定了宏任務和微任務的執行順序。事件循環的基本流程如下:
- 執行全局代碼:當 JavaScript 代碼第一次運行時,首先會執行同步代碼,這些代碼被當作一個宏任務。
- 檢查微任務隊列:一旦宏任務完成,事件循環會檢查并執行微任務隊列中的所有任務,直到隊列為空。
- 執行下一個宏任務:如果微任務隊列為空,事件循環會從宏任務隊列中取出下一個任務并執行。
- 重復上述步驟:這個過程會不斷循環,直到所有任務執行完畢。
3. 宏任務與微任務的執行順序
了解宏任務與微任務的執行順序對于掌握 JavaScript 異步操作非常重要。以下是一些關鍵點:
- 微任務總是在當前宏任務結束后立即執行,優先級高于下一個宏任務。
- 如果在微任務中再次添加微任務,這些新添加的微任務會在當前微任務隊列完成后立即執行。
示例代碼:
console.log('Start'); setTimeout(() => { console.log('setTimeout'); }, 0); Promise.resolve().then(() => { console.log('Promise 1'); }).then(() => { console.log('Promise 2'); }); console.log('End');
執行順序解釋:
- 'Start' 和 'End' 是同步代碼,首先執行。
setTimeout是一個宏任務,它會在宏任務隊列中排隊,等待當前宏任務完成后執行。Promise.then是一個微任務,它會在當前宏任務(即同步代碼執行完畢后)立即執行。- 因此,微任務 'Promise 1' 和 'Promise 2' 會先于
setTimeout的回調執行。 - 最后,
setTimeout的回調會被執行。
輸出順序:
Start End Promise 1 Promise 2 setTimeout
4. 宏任務與微任務的應用場景
理解宏任務和微任務的執行機制可以幫助我們在開發中更好地控制異步操作,避免意外的執行順序。
場景一:控制異步代碼的執行順序
假設我們希望某些異步代碼在其他異步代碼之后執行,利用微任務的高優先級特性,可以確保其順序執行。例如,我們可以使用 Promise.then 來控制執行順序,而不是使用 setTimeout。
場景二:優化性能
在高頻率的用戶交互或動畫渲染場景中,我們可以利用微任務來進行一些輕量的操作,如 DOM 更新或狀態檢查,而將耗時較長的操作放在宏任務中處理。這可以減少 UI 的卡頓,提升用戶體驗。
場景三:避免深度嵌套的回調
在一些復雜的異步操作中,如果直接使用宏任務(如 setTimeout),可能會導致嵌套層級過深,難以維護。利用 Promise 創建微任務可以使代碼更簡潔、可讀性更好,同時也更易于調試。

浙公網安備 33010602011771號