async/await 基本用法(串行运行)
async/await 的提出真正解决了异步过程中‘回调地狱’的问题,使用async/await前请读者先对Promise对象有所了解后进行阅读,Promise用法在笔者上一篇随笔中有所提及。
(async ()=>{
// 抽象一个函数 等待相应的时候后返回成功状态,如果小于0为失败状态
let waitFun = function (time) {
return new Promise((resolve, reject)=>{
if(time>0){
setTimeout(()=>{
resolve(time)
},time)
}else {
reject('执行失败')
}
})
}
//-----------------------------------------------------------------------------------------------------------------------------
console.time()
let r1 =await waitFun(3000)
console.log('输出结果:',r1);
let r2 =await waitFun(2000)
console.log('输出结果:',r2);
let r3 =await waitFun(1000)
console.log('输出结果:',r3);
console.timeEnd()
/**
* 控制台输出:
* 输出结果: 3000
* 输出结果: 2000
* 输出结果: 1000
* default: 6002.86572265625ms
*/
})()
可以看到使用await语法可以将3个异步函数进行串联,在上一个异步函数结束后再执行下一个异步函数,因此理论总耗时为6s。但如果这个三个异步函数数据不相干,想要三个同时请求要如何做到?
async/await 并行运行
实现并行可以通过两种方式:
- 方式1:先声明好多个Promise而后await使用可以使多个计时器同时运行,截止笔者写这篇随便时,还尚未弄清楚其中的原因-_-||。
- 方式2:使用Promise.all()实现。
方式1如下:
console.time('total time')
let fn1 = waitFun(3000);
let fn2 = waitFun(2000);
let fn3 = waitFun(1000);
let r1 = fn1;
console.log('输出结果:',await r1);
let r2 =fn2;
console.log('输出结果:',await r2);
let r3 =fn3;
console.log('输出结果:',await r3);
console.timeEnd('total time')
/**
* 输出结果: 3000
* fn1 time: 3009 ms
*
* 输出结果: 2000
* fn2 time: 3010 ms
*
* 输出结果: 1000
* fn3 time: 3011 ms
*
*
* total time: 3011 ms
*/
方式2如下:
console.time('total time')
await Promise.all([
(async()=>console.log('输出结果:',await waitFun(3000)))(),
(async()=>console.log('输出结果:',await waitFun(2000)))(),
(async()=>console.log('输出结果:',await waitFun(1000)))(),
]);
console.timeEnd('total time')
/**
* 输出结果: 1000
* fn3 time: 1009 ms
*
* 输出结果: 2000
* fn2 time: 2010 ms
*
* 输出结果: 3000
* fn1 time: 3011 ms
*
* total time: 3011 ms
*/
两种方式还是有所不同的虽然总耗时,都是理论3s但方式一的结果是等到所有异步执行完毕按序输出。二方式二则为按照时间输出。推荐方式二。
async/await 在循环中使用
在实际开发中遇到需要在循环中使用的 await的方法,以下是经过各种实验对循环中的await进行可行性总结
foreach循环中使用
在foreach中使用await (结论:不可用)
let list = [{waitTime:3000},{waitTime:2000},{waitTime:1000}];
console.time('total time')
list.forEach( async (item)=>{
console.log('输出结果:',await waitFun(item.waitTime))
});
console.timeEnd('total time')
/**
* total time: 0.610107421875ms
* 输出结果: 1000
* 输出结果: 2000
* 输出结果: 3000
*/
let promiseList = [waitFun(3000),waitFun(2000),waitFun(1000),];
console.time('total time')
promiseList.forEach( async (item)=>{
console.log('输出结果:',await item)
});
console.timeEnd('total time')
// 输出结果同上
个人总结 foreach的参数仅仅一个参数回调而foreach本身并不是一个
AsyncFunction
所有foreach循环本身并不能实现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('输出结果:',await waitFun(list[i].waitTime))
}
console.timeEnd('total time')
输出结果: 3000
输出结果: 2000
输出结果: 1000
total time: 6002.90478515625ms
// 使用 promise 循环如下
for(let i = 0;i<promiseList.length;i++){
console.log('输出结果:',await promiseList[i]);
}
输出结果: 3000
输出结果: 2000
输出结果: 1000
total time: 3001.793212890625ms
结论:由以上结果可以看到 在普通for循环中我依然可以使用 async/await 处理异步操作