問題描述:以下這段代碼的執行結果
async function async1() {
console.log('async1 start');
await async2();
console.log('asnyc1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
setTimeout(() => {
console.log('setTimeOut');
}, 0);
async1();
new Promise(function (reslove) {
console.log('promise1');
reslove();
}).then(function () {
console.log('promise2');
})
console.log('script end');
解決問題:
要了解代碼的執行順序 必須先了解 JS的運作機制
-
有一個Javascript
主線程和main thread
調用棧(執行棧),所有的任務都會被放到調用棧等待主線程執行。call-stack
- JS調用棧采用的是後進先出的規則,當函數執行的時候,會被添加到棧的頂部,當執行棧執行完成後,就會從棧頂移出,直到棧内被清空。
-
單線程任務被分為同步任務和異步任務,同步任務會在調用棧中按照順序等待主線程依次執行,異步任務會在異步任務有了結果後,将注冊的回調函數放入任務隊列中等待主線程空閑的時候(調用棧被清空),被讀取到棧内等待主線程的執行。Javascript

在
JavaScript
中,任務被分為兩種,一種宏任務(
MacroTask
),一種叫微任務(
MicroTask
)。
MacroTask(宏任務)
-
全部代碼、script
、setTimeout
。setInterval
MicroTask(微任務)
-
Promise、await
執行棧在執行完 同步任務後,檢視 執行棧是否為空,如果執行棧為空,就會去檢查 微任務隊列是否為空,如果為空的話,就執行宏任務,否則就一次性執行完所有微任務。
每次單個 宏任務執行完畢後,檢查 微任務隊列是否為空,如果不為空的話,會按照 先入先出的規則全部執行完 微任務後,設定 微任務隊列為
null
,然後再執行 宏任務,如此循環。 運作之前我們需要知道以下幾點
- setTimeout屬于宏任務
- Promise本身是同步的立即執行函數,Promise.then屬于微任務
- async方法執行時,遇到await會立即執行表達式,表達式之後的代碼放到微任務執行
下面我們就來運作代碼
第一次執行:執行同步代碼
Tasks(宏任務):run script、 setTimeout callback
Microtasks(微任務):await、Promise then
JS stack(執行棧): script
Log: script start、async1 start、async2、promise1、script end
第二次執行:執行宏任務後,檢測到微任務隊列中不為空、一次性執行完所有微任務
Tasks(宏任務):run script、 setTimeout callback
Microtasks(微任務):null
JS stack(執行棧): await、Promise then
Log: script start、async1 start、async2、promise1、script end、promise2、async1 end
第三次執行:當微任務隊列中為空時,執行宏任務,執行
setTimeout callback
,列印日志。
Tasks(宏任務):null
Microtasks(微任務):null
JS stack(執行棧):setTimeout callback
Log: script start、async1 start、async2、promise1、script end、promise2、async1 end、setTimeout
關于73以下版本和73版本的差別
- 在老版本版本以下,先執行
,再執行promise2
。async1 end
- 在73及以上版本,先執行
再執行async1 end
。promise2
- 具體資料可以查詢 https://v8.js.cn/blog/fast-async/
于是我們就得到了這段代碼的執行結果(70版本)
(73及以上版本執行結果為)
script start
async1 start
async2
promise1
script end
async1 end promise2 setTimeout
轉載于:https://www.cnblogs.com/dajuyiding/p/11355677.html