JS | Generator 生成器

137 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第22天,点击查看活动详情

在 JS 中,Generator 称之为生成器。它是 ES6 为我们提供的一种异步编程解决方案,除此之外,异步的解决方案还有:

  • 回调函数
  • generator 函数
  • Promise 对象
  • async/await

Generator

Generator 函数会返回一个遍历器对象,它具有 Symbol.iterator 属性。

函数的具体形式是:

  • 函数名之前有一个星号
  • 函数内部使用yield表达式
  • 不能使用箭头函数创建生成器函数
  • Generator 本身并不会自动进行 next 操作,代码中通过手调用 .next() 函数遍历到下一个内部状态
    • 当执行函数遇到 yield 关键词,会将 yield 后面的值作为 value 的值返回
    • 每执行一次 next() 函数,继续向下执行,遇到 yield 关键词为止
    • 如果没有遇到 yield 关键字,继续执行,直到执行到 return 语句
    • 再执行 next(),此时会将 undefined 作为 value 的值返回
function * myFunc() {
    yield 'apple'
    yield 'banana'
    return 'orange'
}
const f = myFunc()
console.log(f.next()) // { value: apple, done: false }
console.log(f.next()) // { value: banana, done: false }
console.log(f.next()) // { value: orange, done: true }
console.log(f.next()) // { value: undefined, done: true }

从运行结果中,可以看到每一步结果是以 { value: , done: } 的形式输出,value 表示当前返回的值,done 表示完成状态(true / false)

image.png

此外,还可以使用 for...of对生成器进行遍历,因为Generator 函数会返回一个遍历器对象(Iterator)

function* func() {
    yield 100;
    yield 200;
    yield 300;
    yield 400;
    yield 500;
    return 600;
}

for (let item of func()) {
    console.log(item);// 100 200 300 400 500
}

运行结果:

image.png

Async/Await 和 Generator

async/await 是 Generator 的语法糖,因为实际上 async 函数就是把 Generator 里的 * 替换成 async,将 yield 替换成了 await,整个流程不需要手动调用 next()

关于 Async/Await 的详细介绍可参考之前的文章: JS进阶 | async/await和Promise的那些事