async await

1. 概述

async 函数是什么?一句话,它就是 Generator 函数的语法糖。
async-await 是promise和generator的语法糖。只是为了让我们书写代码时更加流畅,当然也增强了代码的可读性。简单来说:async-await 是建立在 promise机制之上的,并不能取代其地位。
async 用来表示函数是异步的,定义的函数会返回一个promise对象,可以使用then方法添加回调函数。
await 可以理解为是 async wait 的简写。await 必须出现在 async 函数内部,不能单独使用。
await 后面可以跟任何的JS 表达式。虽然说 await 可以等很多类型的东西,但是它最主要的意图是用来等待 Promise 对象的状态被 resolved。如果await的是 promise对象会造成异步函数停止执行并且等待 promise 的解决,如果等的是正常的表达式则立即执行。

2. 基本用法

2.1 返回 promise 对象

async 函数返回的是一个 promise 对象.

async function test (){
  return 'hello async';
}
let result = test();
console.log(result);
// Promise {<resolved>: "hello async"}

所以,async 函数返回的是一个 Promise 对象。从文档中也可以得到这个信息。async 函数(包含函数语句、函数表达式、Lambda表达式)会返回一个 Promise 对象,如果在函数中 return 一个直接量,async 会把这个直接量通过 Promise.resolve() 封装成 Promise 对象。所以 可以使用 then() 链来处理这个 Promise 对象,就像这样:

test().then(v => {
  console.log(v); // hello async
});

2.2 Promise 对象的状态变化

async 函数返回的 Promise 对象,必须等到内部所有 await 命令后面的 Promise 对象执行完,才会发生状态改变,除非遇到 return 语句或者抛出错误。也就是说,只有 async 函数内部的异步操作执行完,才会执行 then 方法指定的回调函数。

2.3 await 命令

正常情况下,await 命令后面是一个 Promise 对象。如果不是,会被转成一个立即 resolve 的 Promise 对象。

async function f() {
  return await 123;
}

f().then(v => console.log(v))
// 123

上面代码中,await 命令的参数是数值123,它被转成 Promise 对象,并立即 resolve。

await 命令后面的 Promise 对象如果变为 reject 状态,则 reject 的参数会被 catch 方法的回调函数接收到。

async function f() {
  await Promise.reject('出错了');
}

f()
.then(v => console.log(v))
.catch(e => console.log(e))
// 出错了

注意,上面代码中,await 语句前面没有 return,但是 reject 方法的参数依然传入了 catch 方法的回调函数。这里如果在 await 前面加上 return,效果是一样的。

只要一个 await 语句后面的 Promise 变为 reject,那么整个 async 函数都会中断执行。

async function f() {
  await Promise.reject('出错了');
  await Promise.resolve('hello world'); // 不会执行
}

上面代码中,第二个 await 语句是不会执行的,因为第一个 await 语句状态变成了 reject。

有时,我们希望即使前一个异步操作失败,也不要中断后面的异步操作。这时可以将第一个 await 放在 try…catch 结构里面,这样不管这个异步操作是否成功,第二个 await 都会执行。

async function f() {
  try {
    await Promise.reject('出错了');
  } catch(e) {
  }
  return await Promise.resolve('hello world');
}

f()
.then(v => console.log(v))
// hello world

async await

Syntax Error: await is a reserved word

# 报错例:
async submit() {
    try {
        this.$refs[formName].validate(valid => {
            let res = await submit(...this.submitForm)
            this.$message.success(res.resultMessage)
        })
    } catch (err){
        console.log(err)
        this.$message.success(err.resultMessage)
    }
}

上例报错: Syntax Error: await is a reserved word
检查代码 分析: async 在submit()函数前面,里面 validate() 还有一个隐式函数 valid => {},async 应该写在隐式函数前面

#修改后例:
   submit() {
       try {
           this.$refs[formName].validate(async valid => {
               let res = await submit(...this.params)
               this.$message.success(res.resultMessage)
           })
       } catch (err){
           console.log(err)
           this.$message.success(err.resultMessage)
       }
   }

如果有多个 await 命令,可以统一放在 try…catch 结构中。

async main() {
  try {
    const val1 = await firstStep();
    const val2 = await secondStep(val1);
    const val3 = await thirdStep(val1, val2);
    console.log('Final: ', val3);
  }
  catch (err) {
    console.error(err);
  }
}

await in for 循环

let arr = [1, 2, 3, 4, 5];
arr.forEach(async item => {
  await console.log(item)
});