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 处理使得整个异步请求代码清爽了许多。