今天記錄下一個關於js宏任務、微任務、事件輪巡機制的經典面試題:
async function async1(){
console.log("1");
await async2();
// async2();
console.log("2");
}
async function async2(){
console.log("3");
}
console.log("4");
setTimeout(() => {
console.log("5");
Promise.resolve().then(function(){
console.log("6");
});
}, 0);
setTimeout(() => {
console.log("7");
Promise.resolve().then(function(){
console.log("8");
});
}, 0);
async1();
new Promise(function(resolve){
console.log("9");
resolve();
}).then(function(){
console.log("10");
});
console.log("11");
//斷言輸出順序
// 4 => 1 => 3 => 9 => 11 => 10 => 2 => 5 => 7 => 6 => 8
//結果
// 4 => 1 => 3 => 9 => 11 => 2 => 10 => 5 => 6 => 7 => 8
這種東西,你當時看看可能就明白了。過兩天就又忘了,所以寫兩遍看兩遍可能記得牢點,然后看代碼執行順序:
(其實只要記住,宏任務是一個一個的執行,微任務是一下子全執行,執行完一個宏任務就去清空一下微任務棧,一步一步分析就OK。但前提你得知道哪些是宏任務哪些是微任務)
第一遍下來:4 => 將兩個settimeout放入宏任務任務棧 => 1 => 3 然后將await后邊的放入微任務棧 => 9 => 將then里的放入微任務棧 => 11;
然后清空微任務棧:2 => 10;
然后執行宏任務:這時候宏任務里邊放着兩個settimeout,先執行第一個:5=>將后面緊跟着的then放入微任務棧,
然后清空微任務棧:6;
然后執行宏任務:執行另一個宏任務:輸出7 => 將then后邊的放入微任務棧中;
然后清空微任務棧:8;
當然這個是我看完運行結果之后分析的,現在說下我出錯的兩個地方,第一個簡單就是settimeout里邊加Promise這里:大意了,執行settimeout之前微任務棧是空的,執行之后微任務棧就有東西了,自己放的。然后看第二個出錯的地方是:Promise的then和await之后的誰優先,記得在哪里看到過:說then比await優先級高,是真的嗎?
function test2(){ async function async1(){ console.log("1"); await fn(); console.log("2"); } function fn(){ console.log("3"); } async1(); new Promise((resolve,reject)=>{ console.log("4"); resolve(); }).then(_=>{ console.log("5"); }); } // test2(); // 斷言 13425 // 結果13425
看來不是真的,但我真的記得遇見過呀!?
還找到了:
但是我運行下:
function test3(){ 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') } test3(); // 斷言 script start => async1 start => async2 => promise1 => script end => async1 end => promise2 => setTimeout // 運行 script start => async1 start => async2 => promise1 => script end => async1 end => promise2 => setTimeout
和他說的不一樣!用node運行也是一樣!
然后一頓找:發現這個和運行環境的版本有關系,所以就不必過於深究了!WTF!
over!