手写async+await通过generator实现的原理

134 阅读1分钟

首先我们先介绍一下async与await的一些特点,await在使用的时候,如果是promise,会执行.then方法返回结果,如果是数值,会直接返回。

generator实现同步执行的效果

function* generator () {
  const a = yield 1
  console.log(a)
  const b = yield Promise.resolve(2)
  console.log(b)
  const c = yield Promise.resolve(3)
  console.log(c)
}
const generatorTest = generator()
var iteratorResult = generatorTest.next()
iteratorResult = generatorTest.next(iteratorResult.value)
iteratorResult = generatorTest.next(iteratorResult.value)
iteratorResult = generatorTest.next(iteratorResult.value)
输出结果
1
Promise {<fulfilled>: 2}
Promise {<fulfilled>: 3}

手写async + await 自动执行generator

实现的方案实际上是采用了两个核心

1.递归向下自动执行

2.通过Promise.resolve包裹next().value的值对其转化为promise进行返回,便于.then对其解析结果。

function* generator () {
  try {
    const a = yield 1
    console.log(a)
    const b = yield Promise.reject(2)
    console.log(b)
    const c = yield Promise.resolve(3)
    console.log(c)
  } catch (err) {
    console.log('err:' + err)
  }
}

function async (iterator) {
  function handler (iteratorResult) {
    const value = iteratorResult.value
    // 获取当前yield的值
    if (iteratorResult.done) return;
    // 无法确认需要执行的value是值还是promise
    if (value instanceof Promise) {
      value.then(
        res => {
          // res暂时不了解如何赋值给 await前面的变量
          handler(iterator.next(res)) // 通过回调自身的方式自动执行
        },
        err => {
          iterator.throw(err)
        }
      )
    } else {
      handler(iterator.next(value))
    }
  }
  try {
    handler(iterator.next())
  } catch (err) {
    iterator.throw(err)
  }
}

async(generator())

输出结果
1
err:2

以上代码纯属个人想法,有写的不对的欢迎在评论区留言一起讨论学习。