TypeScript 生成器(Generator)
迭代器和生成器这两个概念总是很容易混淆,经过上节的学习我们知道迭代器是一个对象,那么本节首先要记住:生成器是一种能够中途停止,然后从停止的地方继续运行的函数。可以借助 yield
或 return
停止函数运行。
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
可以等待异步函数执行完毕再继续执行后面的代码。
- 还没有人评论,欢迎说说您的想法!