目錄
- 簡介
- 微任務與宏任務的基本概念
- 宏任務(Macrotasks)
- 微任務(Microtasks)
- 宏任務示例
- 微任務示例
- 微任務與宏任務的執行時序
- 結論
簡介
在JavaScript的異步編程中,理解
事件循環(Event Loop)
是至關重要的。事件循環機制確保了JavaScript的單線程能夠處理高并發的異步任務。
微任務(Microtasks)
和宏任務(Macrotasks)
是事件循環中的兩種主要任務類型。
本文將介紹這兩種任務的區別,并通過代碼示例深入探討它們的工作機制,幫助您掌握前端異步編程的核心概念。
微任務與宏任務的基本概念
JavaScript的事件循環由任務隊列組成,任務隊列分為兩種:
微任務隊列和宏任務隊列
。每個宏任務執行完畢后,JavaScript引擎會先執行所有微任務隊列中的任務,然后再執行下一個宏任務。
宏任務(Macrotasks)
宏任務通常指的是那些會在事件循環的單獨迭代中執行的任務,它們包括:
- 整體腳本執行:整個JavaScript文件或腳本標簽作為首次宏任務執行。
- setTimeout 和 setInterval:設定的定時器到期后,會作為宏任務被添加到宏任務隊列。
- setImmediate (Node.js 特有):在Node.js中,
setImmediate
用于在當前事件循環結束時執行。 - I/O:包括從網絡、文件系統等進行的輸入/輸出操作。
- UI 渲染:瀏覽器將計算好的DOM更新渲染到屏幕上。
- requestAnimationFrame:用于動畫的幀同步,會在下一次重繪之前執行。
微任務(Microtasks)
微任務在當前宏任務完成后立即執行,它們包括:
- Promise 回調:
Promise
的.then()
,.catch()
, 和.finally()
方法。 - MutationObserver:用于監聽DOM樹變化的API,當DOM變化時觸發。
- queueMicrotask:一個標準的API,允許開發者顯式地將函數排入微任務隊列。
- process.nextTick (Node.js):在Node.js中,process.nextTick 用于延遲函數的執行直到當前操作結束,但它會在當前執行棧清空之后,下一次事件循環之前執行。
宏任務示例
盡管
setTimeout
的延遲時間設置為0,它仍然是一個宏任務,會在當前宏任務執行完畢后,下一個事件循環迭代中執行。
console.log('Script start');setTimeout(function() {console.log('setTimeout');
}, 0);console.log('Script end');
輸出:
Script start
Script end
setTimeout
微任務示例
Promise
的then
回調是微任務,它們會在當前宏任務的所有代碼執行完畢后立即執行。
console.log('Script start');Promise.resolve().then(function() {console.log('promise1');
}).then(function() {console.log('promise2');
});console.log('Script end');
輸出:
Script start
Script end
promise1
promise2
微任務與宏任務的執行時序
在這個示例中,我們可以看到
Promise
的微任務在當前宏任務的代碼執行完畢后立即執行,而兩個setTimeout
的宏任務則在下一個事件循環迭代中執行。
console.log('Script start');setTimeout(function() {console.log('setTimeout');
});Promise.resolve().then(function() {console.log('promise1');
});setTimeout(function() {console.log('setTimeout2');
}, 0);console.log('Script end');
輸出:
Script start
Script end
promise1
setTimeout2 (next event loop iteration)
setTimeout
結論
- 微任務和宏任務是JavaScript異步編程的基石。
- 微任務提供了一種更快的異步處理方式,通常用于
快速連續的異步操作
,而宏任務則包括了更廣泛的異步事件。