# Generator 函数的语法 (opens new window)

# Generator 函数的异步应用 (opens new window)

# async await的最简实现

经常有人说async函数是generator函数的语法糖,那么到底是怎么样一个糖呢?让我们来一层层的剥开它的糖衣。

# 示例

const getData = () => new Promise(resolve => setTimeout(() => resolve("data"), 1000))

async function test() {
  const data = await getData()
  console.log('data: ', data);
  const data2 = await getData()
  console.log('data2: ', data2);
  return 'success'
}

// 这样的一个函数 应该再1秒后打印data 再过一秒打印data2 最后打印success
test().then(res => console.log(res))

# 思路

对于这个简单的案例来说,如果我们把它用generator函数表达,会是怎么样的呢?

function* testG() {
  // await被编译成了yield
  const data = yield getData()
  console.log('data: ', data);
  const data2 = yield getData()
  console.log('data2: ', data2);
  return 'success'
}

我们知道,generator函数是不会自动执行的,每一次调用它的next方法,会停留在下一个yield的位置。

利用这个特性,我们只要编写一个自动执行的函数,就可以让这个generator函数完全实现async函数的功能。

const getData = () => new Promise(resolve => setTimeout(() => resolve("data"), 1000))
  
var test = asyncToGenerator(
    function* testG() {
      // await被编译成了yield
      const data = yield getData()
      console.log('data: ', data);
      const data2 = yield getData()
      console.log('data2: ', data2);
      return 'success'
    }
)

test().then(res => console.log(res))

那么大体上的思路已经确定了,

asyncToGenerator接受一个generator函数,返回一个promise

关键就在于,里面用yield来划分的异步流程,应该如何自动执行。

下一次调用next的时候,传的参数会被作为上一个yield前面接受的值

function asyncToGenerator(generatorFunc) {
    return function () {
        let gen = generatorFunc.apply(this, arguments)
        return new Promise((resolve, reject) => {
            function step(key, arg) {
                let generatorResult
                try {
                    generatorResult = gen[key](arg)
                } catch (error) {
                    return reject(error)
                }
                const { value, done } = generatorResult
                if (done) {
                    resolve(value)
                } else {
                    Promise.resolve(value).then(res => step('next', res), err => step('throw', err))
                }
            }
            step('next')
        })
    }
}
Last Updated: 12/10/2021, 6:23:25 PM