async/await 基本用法(串行運(yùn)行)
async/await 的提出真正解決了異步過(guò)程中‘回調(diào)地獄’的問(wèn)題辅柴,使用async/await前請(qǐng)讀者先對(duì)Promise對(duì)象有所了解后進(jìn)行閱讀,Promise用法在筆者上一篇隨筆中有所提及瞭吃。
(async ()=>{
// 抽象一個(gè)函數(shù) 等待相應(yīng)的時(shí)候后返回成功狀態(tài)碌嘀,如果小于0為失敗狀態(tài)
let waitFun = function (time) {
return new Promise((resolve, reject)=>{
if(time>0){
setTimeout(()=>{
resolve(time)
},time)
}else {
reject('執(zhí)行失敗')
}
})
}
//-----------------------------------------------------------------------------------------------------------------------------
console.time()
let r1 =await waitFun(3000)
console.log('輸出結(jié)果:',r1);
let r2 =await waitFun(2000)
console.log('輸出結(jié)果:',r2);
let r3 =await waitFun(1000)
console.log('輸出結(jié)果:',r3);
console.timeEnd()
/**
* 控制臺(tái)輸出:
* 輸出結(jié)果: 3000
* 輸出結(jié)果: 2000
* 輸出結(jié)果: 1000
* default: 6002.86572265625ms
*/
})()
可以看到使用await語(yǔ)法可以將3個(gè)異步函數(shù)進(jìn)行串聯(lián),在上一個(gè)異步函數(shù)結(jié)束后再執(zhí)行下一個(gè)異步函數(shù)歪架,因此理論總耗時(shí)為6s筏餐。但如果這個(gè)三個(gè)異步函數(shù)數(shù)據(jù)不相干,想要三個(gè)同時(shí)請(qǐng)求要如何做到牡拇?
async/await 并行運(yùn)行
實(shí)現(xiàn)并行可以通過(guò)兩種方式:
- 方式1:先聲明好多個(gè)Promise而后await使用可以使多個(gè)計(jì)時(shí)器同時(shí)運(yùn)行魁瞪,截止筆者寫這篇隨便時(shí),還尚未弄清楚其中的原因-_-||。
- 方式2:使用Promise.all()實(shí)現(xiàn)惠呼。
方式1如下:
console.time('total time')
let fn1 = waitFun(3000);
let fn2 = waitFun(2000);
let fn3 = waitFun(1000);
let r1 = fn1;
console.log('輸出結(jié)果:',await r1);
let r2 =fn2;
console.log('輸出結(jié)果:',await r2);
let r3 =fn3;
console.log('輸出結(jié)果:',await r3);
console.timeEnd('total time')
/**
* 輸出結(jié)果: 3000
* fn1 time: 3009 ms
*
* 輸出結(jié)果: 2000
* fn2 time: 3010 ms
*
* 輸出結(jié)果: 1000
* fn3 time: 3011 ms
*
*
* total time: 3011 ms
*/
方式2如下:
console.time('total time')
await Promise.all([
(async()=>console.log('輸出結(jié)果:',await waitFun(3000)))(),
(async()=>console.log('輸出結(jié)果:',await waitFun(2000)))(),
(async()=>console.log('輸出結(jié)果:',await waitFun(1000)))(),
]);
console.timeEnd('total time')
/**
* 輸出結(jié)果: 1000
* fn3 time: 1009 ms
*
* 輸出結(jié)果: 2000
* fn2 time: 2010 ms
*
* 輸出結(jié)果: 3000
* fn1 time: 3011 ms
*
* total time: 3011 ms
*/
兩種方式還是有所不同的雖然總耗時(shí)导俘,都是理論3s但方式一的結(jié)果是等到所有異步執(zhí)行完畢按序輸出。二方式二則為按照時(shí)間輸出剔蹋。推薦方式二旅薄。
async/await 在循環(huán)中使用
在實(shí)際開(kāi)發(fā)中遇到需要在循環(huán)中使用的 await的方法,以下是經(jīng)過(guò)各種實(shí)驗(yàn)對(duì)循環(huán)中的await進(jìn)行可行性總結(jié)
foreach循環(huán)中使用
在foreach中使用await (結(jié)論:不可用)
let list = [{waitTime:3000},{waitTime:2000},{waitTime:1000}];
console.time('total time')
list.forEach( async (item)=>{
console.log('輸出結(jié)果:',await waitFun(item.waitTime))
});
console.timeEnd('total time')
/**
* total time: 0.610107421875ms
* 輸出結(jié)果: 1000
* 輸出結(jié)果: 2000
* 輸出結(jié)果: 3000
*/
let promiseList = [waitFun(3000),waitFun(2000),waitFun(1000),];
console.time('total time')
promiseList.forEach( async (item)=>{
console.log('輸出結(jié)果:',await item)
});
console.timeEnd('total time')
// 輸出結(jié)果同上
個(gè)人總結(jié) foreach的參數(shù)僅僅一個(gè)參數(shù)回調(diào)而foreach本身并不是一個(gè)
AsyncFunction
所有foreach循環(huán)本身并不能實(shí)現(xiàn)await效果泣崩。
for中使用
let list = [{waitTime:3000},{waitTime:2000},{waitTime:1000}];
let promiseList = [waitFun(3000),waitFun(2000),waitFun(1000),];
console.time('total time')
for(let i = 0;i<list.length;i++){
console.log('輸出結(jié)果:',await waitFun(list[i].waitTime))
}
console.timeEnd('total time')
輸出結(jié)果: 3000
輸出結(jié)果: 2000
輸出結(jié)果: 1000
total time: 6002.90478515625ms
// 使用 promise 循環(huán)如下
for(let i = 0;i<promiseList.length;i++){
console.log('輸出結(jié)果:',await promiseList[i]);
}
輸出結(jié)果: 3000
輸出結(jié)果: 2000
輸出結(jié)果: 1000
total time: 3001.793212890625ms
結(jié)論:由以上結(jié)果可以看到 在普通for循環(huán)中我依然可以使用 async/await 處理異步操作