一、宏任務和微任務的概念
宏任務和微任務是瀏覽器異步執行任務時的兩種不同類型。當瀏覽器異步執行一個任務時,會首先將任務添加到任務隊列中,然後在執行棧清空後,從任務隊列中取出隊列頭的任務執行。
其中,包括一類稱為宏任務(macro task)的任務,又稱為 task。
還有一類稱為微任務(micro task)的任務,又稱為 jobs。
它們之間的區別在於它們被添加到任務隊列中的時機以及執行的優先級。
二、宏任務和微任務的執行時機
JavaScript 引擎會維護一個執行棧,也稱為調用棧(call stack)。執行棧採用後進先出(LIFO)的原則。
每當 JavaScript 引擎執行一個函數時,它會將該函數加入到執行棧的頂部。當該函數執行結束後,JavaScript 引擎會將它從棧中彈出。
當執行棧被清空時,JavaScript 引擎會從任務隊列中取出一個任務進行執行。
可見,宏任務和微任務的執行時機是不同的。
宏任務通常包括以下幾種:
– setTimeout 和 setInterval 回調函數
– I/O 操作的回調函數
– 事件的回調函數
– setImmediate 回調函數(Node.js 獨有)
而微任務通常包括以下幾種:
– Promise 回調函數
– process.nextTick 回調函數(Node.js 獨有)
三、宏任務和微任務的優先級
在執行棧清空後,JavaScript 引擎會優先處理微任務隊列中的任務,直到隊列為空,然後再在宏任務隊列中取出一個任務執行。也就是說,微任務的優先級高於宏任務。
舉個例子:
“`javascript
setTimeout(() => {
console.log(‘setTimeout’);
}, 0);
Promise.resolve().then(() => {
console.log(‘Promise’);
});
“`
上述代碼中,setTimeout() 和 Promise.resolve().then() 都是異步操作,會被添加到宏任務隊列和微任務隊列中。當執行棧中的所有代碼執行完畢後,JavaScript 引擎會先執行微任務隊列中的 Promise,再執行宏任務隊列中的 setTimeout。因此,上述代碼執行結果為:
Promise
setTimeout
四、宏任務和微任務實例
實例1:
“`javascript
console.log(1);
setTimeout(() => {
console.log(2);
}, 0);
Promise.resolve().then(() => {
console.log(3);
});
console.log(4);
“`
執行過程:
1. 打印 1
2. 添加定時器回調函數到宏任務隊列中
3. 添加 Promise 回調函數到微任務隊列中
4. 打印 4
5. 執行微任務隊列中的 Promise
6. 執行宏任務隊列中的 setTimeout 回調函數
輸出結果為:
1, 4, 3, 2
實例2:
“`javascript
console.log(‘start’);
setTimeout(() => {
console.log(‘setTimeout’);
}, 0);
Promise.resolve().then(() => {
console.log(‘Promise 1’);
}).then(() => {
console.log(‘Promise 2’);
});
console.log(‘end’);
“`
執行過程:
1. 打印 start
2. 添加定時器回調函數到宏任務隊列中
3. 添加 Promise 回調函數到微任務隊列中
4. 打印 end
5. 執行微任務隊列中的 Promise 1
6. 執行 Promise 1 中的 then 回調函數,並將 Promise 2 添加到微任務隊列中
7. 執行微任務隊列中的 Promise 2
8. 執行宏任務隊列中的 setTimeout 回調函數
輸出結果為:
start, end, Promise 1, Promise 2, setTimeout
總結
在 JavaScript 中,宏任務和微任務的概念有助於我們理解異步代碼的執行規則。在掌握了它們之間的區別和優先級後,我們能更加準確地理解和編寫異步代碼,從而提高代碼的效率。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/183057.html