Skip to content

async & await

前言

在探究async/await实现之前,需要先知道generator

链接:MDC Generator DOC

生成器函数

function*这种声明方式 (function关键字后跟一个星号)会定义一个生成器函数 (generator function),它返回一个 Generator 对象,例如。

js
function* idMaker() {
  var index = 0;
  while (index < 3) yield index++;
}

var gen = idMaker();
console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // undefined

Generator对象

MDN中对于Generator的介绍如下

他的原型链上有三个方法nextreturnthrow

简单来说就是

  • 三个方法都返回包含属性 donevalue 的对象,一般情况下
js
function* gen() {
  yield 1;
  yield 2;
  yield 3;
}

const g = gen(); // Generator { }
g.next(); // { value: 1, done: false }
g.next(); // { value: 2, done: false }
g.next(); // { value: 3, done: false }
g.next(); // { value: undefined, done: true }
  • next支持向生成器传入参数,如next(value)
js
function* gen() {
  while (true) {
    const value = yield;
    console.log(value);
  }
}

const g = gen();
g.next(1); // 返回 { value: undefined, done: false }
// 这一步不会有输出:通过 `next` 发送的第一个值会被丢弃
g.next(2); // 返回 { value: undefined, done: false }
// 打印 2
  • return会结束生成器,如果 yield 表达式包含在 try...finally ,从 finally 块产生/返回的值。也支持向生成器传入参数,如return(value)
js
function* gen() {
  try {
    yield 1;
  } finally {
    return "cleanup";
  }
}

const g1 = gen();
g1.next(); // { value: 1, done: false }
g1.return("early return"); // { value: 'cleanup', done: true }
  • throw具有一个参数exception,如throw(exception),这里的exception是要抛出的异常
js
function* gen() {
  while (true) {
    try {
      yield 42;
    } catch (e) {
      console.log("捕获到错误!");
    }
  }
}

const g = gen();
g.next();
// { value: 42, done: false }
g.throw(new Error("出现了些问题"));
// "捕获到错误!"
// { value: 42, done: false }

Async / Await 实现

js
async function request() {
    await new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(1);
            console.log(1);
        }, 600);
    });

    await new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(2);
            console.log(2);
        }, 400);
    });

    await new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(3);
            console.log(3);
        }, 200);
    });
}

request(); // 1 2 3

采用生成器 + 递归的方式实现

js
function* request() {
    yield new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(1);
            console.log(1);
        }, 600);
    });

    yield new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(2);
            console.log(2);
        }, 400);
    });

    yield new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(3);
            console.log(3);
        }, 200);
    });
}

const gen = request();

function rec(g) {
    const next = g.next();
    if (next.done) {
        return;
    }
    next.value.then(() => {
        rec(g);
    });
}

rec(gen);