你知道async/await是怎么实现的吗?

1,261 阅读1分钟

前言

现在ECMAScript6 异步编程,我们都喜欢用 async/await 这种解决方案来处理,写起来代码看起来也很爽。但底层实现原理却比较少人了解,然后最近面试也经常被问到,写篇文章记录下。

async/await 是什么?

我们之前的异步编程方案有回调函数、Promise对象、Generator函数,再到现在E7的async/await。我们通过它的实现原理可以了解到 async/await其实是 Generator 函数的语法糖,可以理解为 async/await = Generator 函数 + 自动执行器

async/await的实现原理

// Generator 函数 + 自动执行器
function spawn (genF) {
  return new Promise(function(resolve, reject) {
    var gen = genF()
    
    function step (nextF) {
      var next
      try {
        next = nextF()
      } catch (error) {
        return reject(error)
      }

      if (next.done) return resolve(next.value)

      Promise.resolve(next.value).then(
        function(value) {
          step(function() {
            return gen.next(value)
          })
        }, 
        function(error) {
          step(function() {
            return gen.throw(error)
          })
        })
    }

    step(function() {
      return gen.next()
    })
  })
}

Generator函数实现async/await使用案例

// 异步函数例子
function wait(time) {
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
      resolve(`wait time: ${time}`)
    }, time)
  })
}

/* generator test start */
function * genF(time = 1000) {
  let res = yield wait(time)
  console.log(res)
}
function asyncByGen() {
  if(typeof arguments[0] !== 'function') throw('first argument must be a function')
  var fn = arguments[0]
  var args = Array.prototype.slice.call(arguments, 1)
  return spawn(fn.bind(null, args))
}
// use 
asyncByGen(genF, 1200) // wait time: 1200
/* generator test end */

/* async test start */
async function asyncF(time = 1000) {
  let res = await wait(time)
  console.log(res)
}
// use 
asyncF(1200) // wait time: 1200
/* async test end */

最后

本文是通过学习阮大神的异步编程系列文章,然后code实现一遍,比之前单纯看文章不code真的要收获更多。每天进步一点点~