JavaScript經過任務隊列管理全部異步任務,而任務隊列還能夠細分爲MacroTask Queue和MicoTask Queue兩類。html
MacroTask Queue(宏任務隊列)主要包括setTimeout, setInterval, setImmediate, requestAnimationFrame, UI rendeing, NodeJS中的`I/O等。promise
MicroTask Queue(微任務隊列)主要包括兩類:bash
1.獨立回調microTask:如Promise,其成功/失敗回調函數相互獨立;異步
2.複合回調microTask:如 Object.observe, MutationObserver 和NodeJs中的 process.nextTick ,不一樣狀態回調在同一函數體;async
JavaScript將異步任務分爲MacroTask和MicroTask,那麼它們區別何在呢?函數
1.先執行同步代碼,遇到異步代碼就先加入隊列,而後按入隊順序執行異步代碼,最後執行setTimeout隊列的代碼
2.setTimeout的任務隊列優先級低於promise隊列,setTimeout的隊列與promise不是一個隊列
3.setTimeout有默認4ms的延遲,因此不會當即執行,而是會進入宏隊列
4.await會讓出當前線程,將後面的代碼加到任務隊列中,而後繼續執行test()函數後面的同步代碼
複製代碼
async function async1() {
console.log("async1 start"); //(2)
await async2();
console.log("async1 end"); //(7)
}
async function async2() {
console.log( 'async2'); //(3)
}
console.log("script start"); //(1)
setTimeout(function () {
console.log("settimeout"); //(8)
},0);
async1();
new Promise(function (resolve) {
console.log("promise1"); //(4)
resolve();
}).then(function () {
console.log("promise2"); //(6)
});
console.log('script end');//(5)
複製代碼
解析:
先按順序執行同步代碼 從‘script start‘開始,
執行到setTimeout函數時,將其回調函數加入隊列(此隊列與promise隊列不是同一個隊列,執行的優先級低於promise)。
而後調用async1()方法,await async2();//執行這一句後,輸出async2後,await會讓出當前線程,將後面的代碼加到任務隊列中,而後繼續執行test()函數後面的同步代碼
繼續執行建立promise對象裏面的代碼屬於同步代碼,promise的異步性體如今then與catch處,因此promise1被輸出,而後將then函數的代碼加入隊列,繼續執行同步代碼,輸出script end。至此同步代碼執行完畢。
開始從隊列中調取任務執行,因爲剛剛提到過,setTimeout的任務隊列優先級低於promise隊列,因此首先執行promise隊列的第一個任務,由於在async函數中有await表達式,會使async函數暫停執行,等待表達式中的 Promise 解析完成後繼續執行 async 函數並返回解決結果。
因此先執行then方法的部分,輸出promise2,而後執行async1中await後面的代碼,輸出async1 end。。最後promise隊列中任務執行完畢,再執行setTimeout的任務隊列,輸出settimeout。
setTimeout(fn,0)的含義是指某個任務在主線程最先可得的空閒時間執行。它在「任務隊列」的尾部添加一個事件,所以要等到同步任務和「任務隊列」現有的時間處理完纔會獲得執行。
複製代碼
僅用於我的整理,參考:post