返回介绍

TypeScript 生成器(Generator)

发布于 2020-06-05 15:08:24 字数 2991 浏览 1555 评论 0 收藏 0

迭代器和生成器这两个概念总是很容易混淆,经过上节的学习我们知道迭代器是一个对象,那么本节首先要记住:生成器是一种能够中途停止,然后从停止的地方继续运行的函数。可以借助 yieldreturn 停止函数运行。

1. 慕课解释

通过 function* 来创建一个生成器函数,在调用一个生成器函数后,并不会立即执行函数中的代码,而是会返回一个迭代器对象,通过调用迭代器对象的 next() 方法,可以获得 yield/return 的返回值。

2. 生成器函数的特殊性

一个正常的函数,如果没有 return 或者 throw 一个异常,一旦被调用在运行结束之前是不会停止的。如果再次调用这个函数,它会再次从第一行开始执行。

function normalFunc() {
  console.log('I')
  console.log('cannot')
  console.log('be')
  console.log('stopped.')
}

In contrast, a generator is a function that can stop midway and then continue from where it stopped.

相反,生成器函数可以中途停止,然后从停止的地方继续执行的。

生成器函数会返回一个对象,可以调用这个对象上的 next() 方法。

3. 示例代码

function* generatorFunction() { 
  console.log('开始执行')
  yield 'Hello, '

  console.log('暂停后再次执行')
  yield 'World!'
}

let iterator = generatorFunction()

此时,通过 function* 语法创建了一个生成器函数,调用这个函数并赋值给变量 iterator,我们已经知道这是个对象。

console.log(iterator.next().value)
// 开始执行
// Hello, 

调用 iterator 对象上的 next() 方法,首先打印出 开始执行,然后遇到了 yield Hello,yield 会将后面的值返回,生成器生成一个对象 { value: 'Hello, ', done: false },函数停止运行,直到再次调用 next() 方法。

console.log(iterator.next().value)
// 暂停后再次执行
// World!

再次调用 next() 方法,函数内继续执行,打印出 暂停后再次执行,遇到 yield 'World!',生成对象 { value: 'World!', done: false },函数停止运行,直到再次调用 next() 方法。

console.log(iterator.next())

再次调用 next() 方法,这次函数内没有返回值,也就是默认返回 undefined, 生成对象 { value: 'undefined', done: true }

4. 通过 next() 参数向生成器传值

在调用 next() 的时候可以传递一个参数,在上次 yield 前接收到这个参数:

function* gen() { 
  console.log('开始执行')
  let res1 = yield 1
  console.log('中断后继续执行')
  console.log(res1)
  
  let res2 = yield 2
  console.log(res2)
  
  console.log('执行结束')
  return 3
}

let iterator = gen()
console.log(iterator.next('first'))
console.log(iterator.next('second'))
console.log(iterator.next('third'))

执行并查看结果:

开始执行
{ value: 1, done: false }
中断后继续执行
second
{ value: 2, done: false }
third
执行结束
{ value: 3, done: true }

这里注意下,生成器最初没有产生任何结果,在第一次调用 next() 时传参是无意义的。

5. 小结

生成器还有另一个巨大的好处,就是把异步回调代码变成“同步”代码。async await 就是基于生成器函数的语法糖,await 可以等待异步函数执行完毕再继续执行后面的代码。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文