async/await 实现原理

287 阅读1分钟

async/await 的用法

  • async 函数返回一个 Promise 对象,当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。
  • async /await 需要在function外部书写async,在内部需要等待执行的函数前书写await即可
function getNum(num){
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(num+1)
        }, 1000)
    })
}
const func = async ()=>{
    const f1 = await getNum(1)
    const f2 = await getNum(f1)
    console.log(f2) 
    // 输出3 
}
func()

async/await 的实现

我们使用函数来模拟

function asyncMain(fn) {
  return function () {
    const self = this
    const arg = arguments
    return new Promise(function (reslove, reject) {
      // 获取迭代器实例
      const generator = fn.apply(self, arg)
      // 执行下一步
      function _next(value) {
        asyncNextStep(generator, reslove, reject, 'next', value, _next, _throw)
      }
      // 抛出异常
      function _throw(error) {
        asyncNextStep(generator, reslove, reject, 'throw', error, _next, _throw)
      }
      // 函数首次执行调用
      _next(undefined)
    })
  }
}
function asyncNextStep(generator, reslove, reject, type, arg, _next, _throw) {
  try {
    // 执行 generator 的 next()
    var info = generator[type](arg)
    var value = info.value
  } catch (error) {
    reject(error);
    return;
  }
  if (info.done) {
    //迭代完成
    reslove(value)
  } else {
    // 递归调用 _next 直到返回 info.done = true
    Promise.resolve(value).then((val) => _next(val));
  }
}

测试代码

function getNum(num) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(num + 1)
    }, 1000)
  })
}

const asyncFunc = asyncMain(function* () {
  const f1 = yield getNum(1)
  const f2 = yield getNum(f1)
  return f2
})

asyncFunc().then(res => {
    // 输出3
    console.log(res);
})