async和await是為了解決異步操作而提出來的規(guī)范,在ES7已經(jīng)實(shí)現(xiàn)了须鼎,可以讓代碼看起來更加像同步代碼雇盖。
下面總結(jié)幾個知識點(diǎn):
1.直接調(diào)用async函數(shù)返回的是一個promise對象
2.await在等待的是后面的返回值 如果是promise的話丽涩,那就會等待最后resolve的值然后返回躁锁,如果是普通值就直接返回
3.async適用于有依賴關(guān)系的異步操作,比如a異步操作返回值為x将饺,后面要用到x贡避,這樣就比較合適,如果沒有依賴予弧,用Promise.all方法會更好刮吧。有依賴的時候,前面的值可以隨時在后頭使用掖蛤,這個是then無法比擬的優(yōu)勢杀捻,因?yàn)榭梢砸恢蹦茫鴗hen在回調(diào)函數(shù)里頭寫的參數(shù)蚓庭,沒有這里await看起來更直觀
4.async函數(shù)內(nèi)部其實(shí)是會發(fā)生阻塞的致讥,await那部分,會返回值也就是resolve的值器赞,后面的相當(dāng)于是then放在了微任務(wù)里頭
async function fun2() {
...
}
async function find() {
let s = await fun2()
}
find()
await其實(shí)是在等后頭的返回值垢袱,其實(shí)是then的語法糖,是想拿到resolve的值拳魁,后頭的代碼都會被阻塞住,也就是在async函數(shù)find里頭執(zhí)行fun2()后頭的代碼全部都會阻塞撮弧,因此會花費(fèi)很多時間潘懊。來看一道面試題,里頭結(jié)合了這些異步的打印順序問題贿衍。
async function async1(){
console.log('1')
await async2()
console.log('2')
}
async function async2(){
console.log('3')
}
console.log('4')
setTimeout(function(){
console.log('5')
},0)
async1();
new Promise(function(resolve){
console.log('6')
resolve();
}).then(function(){
console.log('7')
})
console.log('8')
打印結(jié)果是41368275授舟,在async1里頭,執(zhí)行async2的時候贸辈,阻塞住了释树,后頭的可以理解為then后頭的了,可以知道then就是微任務(wù)擎淤,因此在微任務(wù)的第一個奢啥,所以結(jié)果就是這樣了。
接下來再舉一個例子嘴拢,說明async和await的本質(zhì)
function fn1() {
return new Promise((resolve,reject) => {
setTimeout(() => {
resolve(1)
},5000)
})
}
function fn2() {
return new Promise((resolve,reject) => {
setTimeout(() => {
resolve(2)
},1000)
})
}
async function test() {
let s = await fn1()
console.log('test函數(shù)里頭的同步代碼')
console.log(s);
let s2 = await fn2();
console.log(s2)
}
//相當(dāng)于是fn1().then(s => {
// let s = s;
// console.log('test函數(shù)里頭的同步代碼')
// console.log(s);
// fn2().then(s2 => {
// console.log(s2)
// })
//});
其實(shí)桩盲,就是把a(bǔ)wait函數(shù)后頭的內(nèi)容給放在了fullfillCackbacks里頭,因此不會阻塞席吴,async函數(shù)后頭的代碼運(yùn)行赌结,異步完成了之后捞蛋,就會完成后頭的代碼
var x = test();
console.log(x);
console.log('test后頭的同步代碼')
首先,這里頭的fn1和fn2都可以看成是async函數(shù)柬姚,因?yàn)槎挤祷氐氖且粋€promise對象拟杉,也是就是說,如果加上async的話量承,就不用手動去寫return new Promise這行代碼了搬设,他會自動幫我們包裹處理一下。
所以可以總結(jié)async函數(shù)和await的本質(zhì)了宴合,直接調(diào)用async函數(shù)的時候焕梅,返回的是整個 大的promise對象,而async里頭的代碼都是這個大的promise對象的executor同步代碼卦洽,會立即執(zhí)行贞言,執(zhí)行executor函數(shù)的時候,是因?yàn)閒n1是返回的promise阀蒂,而且還是pending態(tài)的该窗,這個await相當(dāng)于就分隔開了async函數(shù)內(nèi)部的代碼段,await就是then的語法糖蚤霞,fn1之后酗失,拿到resolve的值然后給s,但是因?yàn)槭莗ending昧绣,所以加入到了fullfillcackbacks里頭等待resolve的時候去回調(diào)即可规肴,后頭的await也是同理。
所以async函數(shù)里頭的代碼其實(shí)和promise是一樣的原理夜畴,then里頭的東西加到了fullfillcallbacks里頭拖刃,因此后頭的代碼是不會被阻塞的。