Skip to content

Generator 是什么? ​

Generator 是可以暂停的函数。执行到 yield 就停下,并把一个值交出来;下次 next 再从那里继续。它适合按需产生序列,也是早期异步流程控制的一种写法。现在异步流程优先用 async/await。

原理 ​

js
function* ids() {
  yield 1
  yield 2
}
const g = ids()
g.next() // { value: 1, done: false }
g.next() // { value: 2, done: false }
g.next() // { value: undefined, done: true }

next 可以传入值,这个值成为上一个 yield 表达式的结果。调用方因此能把数据送回生成器。return 和 throw 用来从外面结束或抛错。

生成器对象是可迭代的,可以用 for...of 和展开。for...of 在 done: true 时停止,不会消费最后那个 value。

yield* 把迭代委托给另一个可迭代对象。

追问 ​

和 async 函数的关系?

async 函数在实现历史上可以看成返回 Promise 的生成器。现在语言有独立的 async/await。生成器仍适合无限序列、分步状态机,以及需要调用方推进的惰性计算。

怎么做无限序列?

while (true) yield n++。消费者只取有限次就不会死循环。不要对无限生成器展开或 Array.from。

易错点 ​

  • 调用生成器函数不会立刻执行函数体,要 next 才跑到第一个 yield。
  • 每次调用生成器函数得到一个新的迭代器,旧的暂停位置不会共享。
  • for...of 拿不到 return 的完成值。

相关 ​