外观
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的完成值。