1、JS是單線程語言,包括同步任務、異步任務,異步任務又包括宏觀任務和微觀任務
2、執(zhí)行順序:同步任務——>微觀任務——>宏觀任務
3、宏觀任務的方法有:script(整體代碼)、setTimeout、setInterval、I/O、UI交互事件、postMessage、MessageChannel、setImmediate(Node.js 環(huán)境)
4、微觀任務的方法有:Promise.then、MutaionObserver、process.nextTick(Node.js 環(huán)境),async/await實際上是promise+generator的語法糖,也就是promise,也就是微觀任務
1. setTimeout
console.log('script start') //1. 打印 script start
setTimeout(function(){
console.log('settimeout') // 4. 打印 settimeout
}) // 2. 調用 setTimeout 函數,并定義其完成后執(zhí)行的回調函數
console.log('script end') //3. 打印 script start
// 輸出順序:script start->script end->settimeout
2. Promise
console.log('script start')
let promise1 = new Promise(function (resolve) {
console.log('promise1')
resolve()
console.log('promise1 end')
}).then(function () {
console.log('promise2')
})
setTimeout(function(){
console.log('settimeout')
})
console.log('script end')
// 輸出順序: script start->promise1->promise1 end->script end->promise2->settimeout
3. async/await
async function async1(){
console.log('async1 start');
await async2();
console.log('async1 end')
}
async function async2(){
console.log('async2')
}
console.log('script start');
async1();
console.log('script end')
// 輸出順序:script start->async1 start->async2->script end->async1 end
執(zhí)行先后順序 setTimeout、Promise、Async/Await 對比
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
}
console.log('start');
setTimeout(() => {
console.log('setTimeout');
}, 0);
async1();
new Promise(resolve => {
console.log('promise1');
resolve();
}).then(() => {
console.log('promise2');
})
console.log('end');
運行結果
start
async1 start
async2
promise1
end
promise2
async1 end
setTimeout
調用順序問題解析:
async 會定義一個返回 AsyncFunction 對象的異步函數。即以 async 聲明的函數,會隱式地返回一個 Promise 對象。當這個 async 函數返回一個值時,Promise 的 resolve 方法會負責傳遞這個值;當 async 函數拋出異常時,Promise 的 reject 方法也會傳遞這個異常值。
await 操作符用于等待一個 Promise 對象。它返回 Promise 對象的處理結果。如果等待的不是 Promise 對象,則返回該值本身。
注意:
await 只能在異步函數 async function 中使用。
如果你希望并行等待兩個或者是更多的 Promise 對象,你必須使用Promise.then,而不是await。
隊列任務優(yōu)先級:promise.Trick() > promise的回調 > setTimeout > setImmediate
因此上述代碼可以理解成:(部分用語可能不準確)
在同步執(zhí)行階段:
async1執(zhí)行到await async2()時,sync2()返回一個Promise, 其resolve放入到回調隊列中,跳出async1,執(zhí)行new promise的resolve時,該resolve也會被放入回調隊列中。然后執(zhí)行到console.log('end');,此時同步執(zhí)行結束。
重點(執(zhí)行回調隊列):
此時async2()返回的 Promise的resolve會被執(zhí)行,即執(zhí)行await async2(),此時await的Promise的resolve會被放入到新回調隊列。此時原回調隊列中new promise的resolve會被執(zhí)行,promise2字符被打印,原回調隊列執(zhí)行完畢。
執(zhí)行新回調隊列:
await的Promise的resolve被執(zhí)行,console.log('async1 end')執(zhí)行。async1()返回的Promise的resolve會被放入到新回調隊列。
所有回調隊列執(zhí)行完畢,setTimeout執(zhí)行。