生成器runner

6/15/2021 js

提示

在使用生成器函数(function* () {...})进行一系列异步操作时,我们一般都不想每次在每个yield异步请求完成时手动调用生成器实例的next方法进行迭代,可能更加需要一个runner自动迭代

/*
  调用方式
  run(function* gen () {
    yield function () {}
  
    yield new Promise((resolve, reject) => {
      // ...一系列异步操作
    })
  }).then(() => {}).catch(() => {})
  返回Promise
*/

function run (gen) {
  const arg = [].slice.call(arguments, 1)
  const it = gen.apply(this, arg) // 在当前环境下调用生成器函数
  return Promise.resolve()
    .then(function handleNext(value) {
      const next = it.next(value)
      return (function handleResult({ value: val, done }) {
        if (done) return val // 判断是否结束
        return Promise.resolve(val)
          .then(
            handleNext,
            err => {
              return Promise.resolve(it.throw(err)) // throw方法被捕获以后,会附带执行下一条yield表达式(就是会附带执行next方法)
                .then(handleResult)
            }
        )
      })(next)
    })
}
// 调用
function *foo () {
  try {
    yield Promise.reject(123)
  } catch (err) {
    console.log(err)
  }
  yield 123
  yield Promise.resolve(111)
}
run(foo).then(res => console.log(res))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

提示

async函数其实就是生成器函数的语法糖,async函数就是将生成器函数的星号(*)替换成async,将yield替换成await,生成器函数的执行必须需要类似runner的执行器,async函数原理类似runner,返回一个promise

最后更新时间: 12/4/2022, 1:44:46 PM