微任務和宏任務有什麼區別?

王铁柱6發表於2024-12-01

在前端開發中,微任務(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

解釋:

  1. StartEnd 同步執行並列印。
  2. setTimeoutPromise.then 都是非同步操作,被新增到各自的佇列中。
  3. 儘管 setTimeout 的延遲時間為 0,但它仍然是一個宏任務,會在當前宏任務 (主執行緒的同步程式碼) 執行完畢後才執行。
  4. 在當前宏任務執行完畢後,事件迴圈會檢查微任務佇列,發現 Promise.then,於是先執行 Promise.then 並列印 Promise.then
  5. 最後,事件迴圈取出 setTimeout 這個宏任務並執行,列印 setTimeout

理解微任務和宏任務的區別對於控制程式碼執行順序、避免競態條件以及編寫高效的非同步程式碼至關重要。 例如,在處理 UI 更新時,使用微任務可以確保在瀏覽器重新渲染之前完成所有必要的 DOM 操作,從而避免閃爍和效能問題。

相關文章