ES2017 异步处理 async/await
1. 什么是 async/await
async 顾名思义是“异步”的意思,async 用于声明一个函数是异步的。而 await 从字面意思上是“等待”的意思,就是用于等待异步完成。并且 await 只能在 async 函数中使用。
通常 async、await 都是跟随 Promise 一起使用的。为什么这么说呢?因为 async 返回的都是一个 Promise 对象。同时 async 适用于任何类型的函数上。这样 await 得到的就是一个 Promise 对象(如果不是 Promise 对象的话那 async 返回的是什么就是什么);
await 得到 Promise 对象之后就等待 Promise 接下来的 resolve 或者 reject。
来看一段简单的代码:
async function testSync() {
const response = await new Promise(resolve => {
setTimeout(() => {
resolve("async await test...");
}, 1000);
});
console.log(response);
}
testSync(); //async await test...
就这样一个简单的 async、awai t异步就完成了。使用 async、await 完成异步操作代码可读与写法上更像是同步的,也更容易让人理解。
2. async、await串行并行处理
2.1 串行
等待前面一个 await 执行后接着执行下一个 await,以此类推;
async function asyncAwaitFn(str) {
return await new Promise((resolve, reject) => {
setTimeout(() => {
resolve(str)
}, 1000);
})
}
const serialFn = async () => { //串行执行
console.time('serialFn')
console.log(await asyncAwaitFn('string 1'));
console.log(await asyncAwaitFn('string 2'));
console.timeEnd('serialFn')
}
serialFn();
可以看到两个 await 串行执行的总耗时为两千多毫秒。
2.2 并行
将多个 promise 直接发起请求(先执行 async 所在函数),然后再进行 await 操作。
async function asyncAwaitFn(str) {
return await new Promise((resolve, reject) => {
setTimeout(() => {
resolve(str)
}, 1000);
})
}
const parallel = async () => { //并行执行
console.time('parallel')
const parallelOne = asyncAwaitFn('string 1');
const parallelTwo = asyncAwaitFn('string 2')
//直接打印
console.log(await parallelOne)
console.log(await parallelTwo)
console.timeEnd('parallel')
}
parallel()
通过打印我们可以看到相对于串行执行,效率提升了一倍。在并行请求中先执行 async 的异步操作再 await 它的结果,把多个串行请求改为并行可以将代码执行得更快,效率更高。
3. async/await的错误处理
JavaScript 异步请求肯定会有请求失败的情况,上面也说到了 async 返回的是一个 Promise 对象。既然是返回一个 Promise 对象的话那处理当异步请求发生错误的时候我们就要处理 reject 的状态了。
在 Promise 中当请求 reject 的时候我们可以使用 catch。为了保持代码的健壮性使用 async、await 的时候我们使用 try catch 来处理错误。
async function catchErr() {
try {
const errRes = await new Promise((resolve, reject) => {
setTimeout(() => {
reject("http error...");
}, 1000);
);
//平常我们也可以在await请求成功后通过判断当前status是不是200来判断请求是否成功
// console.log(errRes.status, errRes.statusText);
} catch(err) {
console.log(err);
}
}
catchErr(); //http error...
虽然 async、await 也使用到了 Promise 但是却减少了 Promise 的 then 处理使得整个异步请求代码清爽了许多。