以下是學習async起愈、await時遇到的問題,現在把它們簡化译仗、說明一下
- 問題一
async function A(){
setTimeout(()=>{
return 777
},1000)
}
(async function(){
var a = await A()
console.log(a)
})()
----------------------
undefined
返回值為undefined抬虽。不是說在async中返回一個值,這個值就是Promise中reslove的值嗎纵菌?但后來檢查才發(fā)現——上面函數中的return是在回調函數的代碼塊中阐污,只有直接在async函數中return才可以被reslove傳遞。
- 問題二
既然在回調函數中return得不到想要的結果咱圆,那我改成下面這樣總該行了吧笛辟。
async function A(){
setTimeout(()=>{
console.log('被延遲執(zhí)行的一句話')
},1000)
}
(async function(){
console.log('start')
await A()
console.log('end')
})()
不用想功氨,輸出的結果肯定是
start
被延遲執(zhí)行的一句話
end
但結果是....
start
end
被延遲執(zhí)行的一句話
what?? 后來查了資料才明白
await會暫停當前async函數的執(zhí)行,等待后面的Promise的計算結果返回以后再繼續(xù)執(zhí)行當前的async函數手幢。
也就是說異步操作如果不改造成promise形式 或者 沒有正確使用async的語法改造捷凄,await是不會生效的。
因為這段代碼不需要返回值围来,所以用async改造也不會生效跺涤,那我們的代碼就寫成下面的樣子來測試:
async function A(){
return new Promise((reslove,reject)=>{
setTimeout(()=>{
console.log('被延遲執(zhí)行的一句話')
reslove()
},1000)
})
}
(async function(){
console.log('start')
await A()
console.log('end')
})()
--------------------------
start
被延遲執(zhí)行的一句話
end
這樣結果就是我們想要的了。
- 問題三:await是否阻塞了代碼
終于得到了想要的結果监透,但好像哪里不對勁...哎桶错?這樣await不就阻塞了下面同步代碼的執(zhí)行了嗎?如果我await一個讀取大文件的函數胀蛮,豈不是要等很久才能執(zhí)行下面的代碼院刁?
既然async、await是promise的語法糖粪狼,那我試一下promise的寫法會是什么效果:
async function A(){
return new Promise((reslove,reject)=>{
setTimeout(()=>{
console.log('被延遲執(zhí)行的一句話')
reslove()
},1000)
})
}
(async function(){
console.log('start')
var p = A()
p.then()
console.log('end')
})()
--------------------------
start
end
被延遲執(zhí)行的一句話
也就是說promise就像正常的異步一樣退腥,沒有阻塞同步代碼運行。
為了考證一下await是不是阻塞了代碼的正常執(zhí)行鸳玩,我寫了以下的代碼:
function B(){
return new Promise((reslove,reject)=>{
setTimeout(()=>{
console.log('被延遲執(zhí)行的一句話')
reslove()
},1000)
})
}
(async function(){
var i=0
var timer = setInterval(function(){
i+=1
if(i===50){
clearInterval(timer)
}
console.log('-----')
},100)
console.log('start')
await B()
console.log('end')
})()
----------------------------
start
10 -----
被延遲執(zhí)行的一句話
end
40 -----
由此說明阅虫,await沒有阻塞異步代碼的運行,但后面的同步代碼確實被await“擋住了”不跟。如果寫在async里面的同步代碼會被await擋住颓帝,那寫在async外的同步代碼呢?我又做了以下試驗:
function A(){
return new Promise((reslove,reject)=>{
setTimeout(()=>{
console.log('被延遲執(zhí)行的一句話 A')
reslove()
},1000)
})
}
(async function(){
console.log('start A')
await A()
console.log('end A')
})()
console.log('我是同步代碼')
----------------------------
start A
我是同步代碼
被延遲執(zhí)行的一句話 A
end A
疑惑終于被打破窝革,至此我得出一個結論(這個結論只是方便理解)————
類比上面的then函數來看购城,await后面要執(zhí)行的同步代碼其實本應該就是寫在then的回調函數里的,而await必須在async代碼塊中執(zhí)行的原因虐译,正是要創(chuàng)建一個類似于then函數參數中的回調函數的執(zhí)行環(huán)境瘪板,這樣就可以保證異步代碼不會阻塞同步代碼。所以在async代碼塊中漆诽,await后面只寫需要等待回調結果的代碼侮攀, 不相關的代碼必須要寫到async代碼塊以外的地方去。
async厢拭、await要點:在返回Promise的函數上使用await兰英、使用try catch獲取await的結果、根據多個promise返回結果還是要配合Promise.all()供鸠、Promise.race()使用
有理解不到位的地方還請多多指教畦贸。