setTimeout 、 promise、async await 的執行順序?宏任務、微任務,分別包含哪些?


JS 分為同步任務和異步任務

同步任務在主線程上執行

異步任務放在主線程之外的一個任務隊列

主線程執行完畢后,讀取任務隊列的內容

 

宏任務(macro)task:當前主線程上執行的就是一個宏任務。例: script 的代碼、setTimeout、setInterval、postMessage等。

微任務:microtask。例:Promise.then、await后面的代碼。

在執行當前宏任務時(同步執行時),遇到 setTimeout 會把它放到宏任務隊列。遇到Promise.then會放到微任務隊列。

當前 宏任務 執行完畢后,會先查看微任務隊列,如果有任務,優先執行,否則執行下一個宏任務。所以 promise.then 會先於 setTimeout執行。

 

試試這段代碼(頭條):

//請寫出輸出內容
async function async1() {
    console.log('async1 start');
    await async2();
    console.log('async1 end');
}
async function async2() {
	console.log('async2');
}

console.log('script start');

setTimeout(function() {
    console.log('setTimeout');
}, 0)

async1();

new Promise(function(resolve) {
    console.log('promise1');
    resolve();
}).then(function() {
    console.log('promise2');
});
console.log('script end');


//打印結果
/*
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout
*/

 

根據上面的原則來,基本沒啥問題了。但是肯定有個疑惑的地方。為什么 “async1 end” 跑到了倒數第三個。

那是因為 async 函數中,遇到 await 會跳出當前函數,並讓出線程,再將await后面的代碼放到 微任務(microtask)隊列中

 

整個執行過程:

1、同步執行, 輸出“script start”。

2、遇到setTimeout,將里面代碼放到宏任務隊列。

3、繼續往下,輸出 “async1 start”,然后執行 async2函數,輸出 “async2”。

4、async2執行完畢,將await async2 后面的代碼加入到 微任務隊列;

5、繼續執行,new Promise, 同步輸出“promise1”。

6、遇到 promise.then,加入到微任務隊列,

7、然后輸出 "script end"。

8、當前宏任務執行完畢,查看微任務隊列,按照先進先出原則。

9、依次輸出“async1 end”、“promise2”

10、執行下一個宏任務,里面只有一個setTimeout,所以最后輸出 “setTimeout”

 

同步執行的:[script start] [async1 start] [async2] [promise1] [script end]

微任務隊列:[async1 end] [ promise2 ]

宏任務隊列:[setTimeout]


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM