JS中的Generator函数

Generator函数是ES6的异步编程解决方案,它封装了内部状态并返回可迭代对象。使用next()方法执行并由yield表达式控制流程。通过return()或throw()可以停止并返回值或错误。Generator在处理无限数据流和模拟async/await中尤其有用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Generator 函数是 ES6 提供的一种异步编程解决方案,它是一个状态机,封装了多个内部状态;它提供一种有效的方式来制作迭代器,并且能够处理无限数据流;当与Promises一起使用时,生成器可以模拟async/await功能,这使我们能够以更直接和可读的方式处理异步代码。

接下来开始正文

1. Generator 函数

generator函数返回一个Generator对象,并且它是通过function关键字后跟一个星号*来定义的,如下所示:

// Generator function declaration
function* generatorFunction() {}

当然还有另一种写法

// Generator function declaration
function *generatorFunction() {}

这两种写法产生的效果都是一样的,不过后面这种不太常写。

generator函数可以在表达式中定义:

// Generator function expression
const generatorFunction = function* () {}

生成器甚至可以是对象或类的方法:

// Generator as the method of an object
const generatorObj = {
  *generatorMethod() {},
}

// Generator as the method of a class
class GeneratorClass {
  *generatorMethod() {}
}

注意:与常规函数不同,生成器不能使用new关键字构造,也不能与箭头函数结合使用

2. Generator对象

JavaScript中的普通函数会运行到完成状态,调用函数会在到达return关键字时返回一个值。如果return省略关键字,则函数将隐式返回undefined。
如下:

function sum(a, b) {
  return a + b
}
const value = sum(5, 6) //11

这种普通的函数会直接返回一个值,但是Generator函数却不会立即返回一个值,而是返回一个可迭代的Generator对象。如下所示:

function* generatorFunction() {
  return 'Hello, Generator!'
}
const generator = generatorFunction()
console.log(generator)

输出的结果如图,我们实际上得到的是处于suspended状态的对象
在这里插入图片描述

3.next()方法

generator函数返回的对象是一个迭代器(iterator Object)。为了输出结果,就需要使用迭代器中next()方法。该next()方法返回具有value和done属性的对象。value代表返回的值,并done指示迭代器是否已遍历其所有值。

接下来使用next()方法,看看输出什么

generator.next()

输出结果为:{ value: 'Hello, Generator!', done: true }

这回输出了我们想要的结果

接着我们再看看generator的状态
在这里插入图片描述
由于迭代器已运行完成,因此generator对象的状态将从suspended变为closed。

4.yield 表达式

generator函数内部还引入了一个关键字yield,yield可以暂停generator函数并返回yield后的值,从而提供了一种轻量级的方法来遍历值。
接下来看一个例子:

function* generatorFunction() {
  yield '1'
  yield '2'
  yield '3'

  return 'end'
}

const generator = generatorFunction()
 // 分别调用四次next()
generator.next()
generator.next()
generator.next()
generator.next()

接着看看每次调用的结果

{value: "1", done: false}
{value: "2", done: false}
{value: "3", done: false}
{value: "end", done: true}

5. generator函数的迭代

generator函数返回一个迭代器,所以它也遵守迭代协议,可以使用for…of…等进行输出。
看下面例子:

function* generatorFunction() {
  yield '1'
  yield '2'
  yield '3'

  return 'end'
}

const generator = generatorFunction()
for (const value of generator) {
  console.log(value)
}

这个输出结果为: 1 2 3

除了for of ,也可以使用扩展符号(…)进行输出

function* generatorFunction() {
  yield '1'
  yield '2'
  yield '3'

  return 'end'
}

const generator = generatorFunction()
const value = [...generator]
console.log(value)

输出结果为: [ ‘1’, ‘2’, ‘3’ ]

虽然这两种方法都适用于generator函数,但是如果generator函数正在处理无限数据流时,则这两种方法使用便受限了。

6. 停止generator函数

上面讲的如何执行generator函数,接下来介绍如何终止generator函数:即使用return()方法和throw()方法

6.1 return

使用return(),可以在任何时候终止生成器,就像return在函数体内有一条语句一样。您可以将参数传递到中return(),也可以将其保留为空白以获取未定义的值。

function* generatorFunction() {
  yield 'a'
  yield 'b'
  yield 'c'
}

const generator = generatorFunction()

generator.next()
generator.return('end!!')
generator.next()

输出结果为

{value: "a", done: false}
{value: "end!!", done: true}
{value: undefined, done: true}

再执行完return之后,generator对象的状态就变为closed了

generatorFunction {<closed>}
__proto__: Generator
[[GeneratorLocation]]: VM36:1
[[GeneratorStatus]]: "closed"
[[GeneratorFunction]]: ƒ* generatorFunction()
[[GeneratorReceiver]]: Window

该return()方法强制Generator对象完成并且忽略任何其他yield关键字,这在异步编程中特别有用,例如当用户想要执行其他操作而需要中断Web请求时,我们无法直接取消Promise,所以可以使用这种方法。

6.2 throw

使用throw方法是利用try…catch…会捕获错误并处理错误的这种能力,详见下面例子:

function* generatorFunction() {
  try {
    yield 'a'
    yield 'b'
  } catch (error) {
    console.log(error)
  }
}

const generator = generatorFunction()
generator.next()
generator.throw(new Error('ERROR!'))

输出结果为:

{value: 'a', done: false}
Error:ERROR!
{value: undefined, done: true}

使用return和throw都是可以实现中断generator函数的。

7. 小结

在generator函数中,可以使用三种方法:

  • next() :返回迭代器中的下一个值
  • return():中断迭代器并返回一个值
  • throw():中断迭代器并返回报错信息

在generator对象中,有两种状态“

  • suspended:迭代器已暂停执行但尚未终止
  • closed:迭代器因遇到错误,返回或遍历所有值而终止
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值