# 10 分钟回顾一下 Promise 和 async/await

  • 这里我们不对基础概念有过多的介绍,开始之前,如果对 eventLoop 还不太熟悉的同学可以回顾一下之前的文章Event Loop

# 基于观察者模式实现一个简易版本的 Promise

  • 目前我们先不考虑完美的 Promise 的paddingfulfilledrejected三种状态,以及finallyallraceallSettled等方法和异常情况的处理,用 12 行代码实现不完整的 Promise 异步链式调用,了解 Promise 的设计思路
function MiniPromise(fn) {
  var callbacks = [];
  function resolve(value) {
    callbacks.forEach((callback) => {
      //循环通知观察者
      callback(value);
    });
    callbacks = [];
  }
  this.then = function (cb) {
    callbacks.push(cb);
  };
  fn(resolve);
}
  • 我们拿着上面的构造函数来试验一下
new MiniPromise((resolve) => {
  console.log('start');
  setTimeout(() => {
    console.log('success');
    resolve('ok');
  }, 2000);
}).then((res) => {
  console.log(666);
  console.log(res);
});
// success
// 666
// ok

# 分析

  • 其核心就是一个依赖收集,等待实例的异步函数被调用后,再把我们的依赖一个个依次执行
  • 但是完整的 Promise 还是比这个复杂很多,有兴趣的小伙伴可以对着Promises/A+ (opens new window)继续实现下去

# 更优雅的 async/await

  • 虽然链式调用解决了回调地狱,但是总体的可读性还是不佳,而解决异步调用的终极方案,就是 ES7 提出的async/await函数
  • async/await实际上糖是Generator(生成器)函数的语法糖,对Generator函数改进并封装
    • Generator 函数中可以通过 yield 关键字,把函数的执行流挂起,再手动调用next()切换到下一个状态(移动内部指针),在next()中还可以通过传参使让yield具有返回值,从而实现改变执行流程
function* miniAsync(a) {
  // await被编译成了yield
  const template = yield a + 1;
  console.log('data: ', template);
  return 'end';
}
const res = miniAsync(1);
res.next(1); // { value: 2, done: false }
res.next(); // { value: underfind, done: true }
  • 调用一次 Generator 会在 yield 所在位置停下并执行当行后返回一个包含 value、done 两个键值对的 Object,直到下一次调用或最后代码执行完毕再返回一个 done 为 true 的对象
  • 相比于async/awaitGenerator需要手动调用,而且返回的是 Object 对象不是 Promise 对象,并且 await 能够接收异步返回值

# 原理

  • async/await实际上是 Generator 结合自执行函数(spawn)
async function fn(args) {
  // ...
}

// 等同于

function fn(args) {
  return spawn(function* () {
    // ...
  });
}
# 以上!感谢各位看官老爷!
Last Updated: 6/2/2022, 3:50:31 AM