Skip to content

简介 ​

  • async/await 是基于 Promise 实现的,不能用于普通的回调函数
  • async/await 与 Promise 一样是非阻塞的
  • async/await 使得异步代码看起来像同步代码

基本用法 ​

async 函数就是 Generator 函数的语法糖,它的改进如下:

  • 内置执行器,与普通函数一样。
  • 更语义,async 和 await ,比起星号和 yield。
  • 更广的适应性,async 函数的 await 命令后面,可以是 Promise 对象和原始类型的值
  • 返回值是 Promise,可以用 then 指定下一步操作

async 的使用形式 ​

// 函数声明
async function foo() {}
// 函数表达式
const foo = async function () {};
// 对象的方法
let obj = { async foo() {} };
obj.foo().then(...)
// 箭头函数
const foo = async () => {};
// Class 的方法
class Storage {
    async getAvatar(name) {
        const cache = await this.cachePromise;
        return cache.match(`/avatars/${name}.jpg`);
    }
}

返回 Promise 对象 ​

async 函数返回一个 Promise 对象,async 函数内部 return 语句的返回值会成为 then 方法回调函数的参数。 async 函数内部抛出错误会导致返回的 Promise 对象变为 reject 状态,错误对象会被 catch 方法接收到。

Promise 对象状态变化 ​

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

await 命令 ​

await 命令后面是一个 Promise 对象。如果不是,会被转成一个立即 resolve 的 Promise 对象。 只要一个 await 语句后面的 Promise 变为 reject ,那么整个 async 函数都会中断执行。

错误处理 ​

如果 await 后面的异步操作出错,那么等同于 async 函数返回的 Promise 对象被 reject 且后续操作会被中断

  • await 放在 try...catch 结构里面
  • await 后面的 Promise 对象再跟一个 catch 方法

使用注意点 ​

  • 最好把 await 命令放在 try...catch 代码块中
  • 多个 await 命令后面的异步操作,如果不存在继发关系,最好让它们同时触发。
// 写法一
let [foo, bar] = await Promise.all([getFoo(), getBar()]);
// 写法二
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;
  • await 命令只能用在 async 函数之中,如果用在普通函数,就会报错

async 实现的原理 ​

  • async 函数的实现原理就是将 Generator 函数和自动执行器,包装在一个函数里。
javascript
async function fn(args) {
  // ...
}
// 等同于(spawn函数就是自动执行器)
function fn(args) {
  return spawn(function* () {
    // ...
  });
}