- 前言
- 一个例子了解生成器
- 基本概念
- 如何理解 Generator 函数是状态机?
- next 传递参数
- 与 Iterator 接口的关系
- 提前终止生成器
- next()、throw()、return() 的共同点
- yield* 表达式

在上面的代码中,执行 next 函数,使得 try 代码块开始执行,再调用 return 方法,就会开始执行 finally 代码块,然后等待执行完毕,再返回 return 方法指定的返回值。
throw
throw() 方法会在暂停的时候将一个提供的错误注入到生成器对象中。如果错误未被处理,生成器就会关闭。
在很多的资料中都说的很复杂,其实就很简单:
有错误你就给我一个 catch 来处理掉,不然你就给我退出,就是这么霸道。
function* gen(){
console.log("state1");
let state1 = yield "state1";
console.log("state2");
let state2 = yield "state2";
console.log("end");
}
let g = gen();
g.next();
g.throw();
在上面的代码中,throw 方法提出的错误,没有被处理,因此会被直接退出,因此上面的代码只会输出 state1 ,然后报错
注意:可以给 throw 方法传递参数,用来解释错误。
g.throw(new Error('出错了!'))
next()、throw()、return() 的共同点
到这里遍历器对象的 3 个方法,已经都涉及过了,虽然他们的功能各不相同,或者说完全没有关系,但是他们的本质确实在做同一件事,“采用语句替换 yield 表达式”。
next 是将 yield 表达式替换成一个值。
throw是将 yield 表达式替换成 throw 语句。
gen.throw(new Error('出错了')); // Uncaught Error: 出错了
// 相当于将 let result = yield x + y
// 替换成 let result = throw(new Error('出错了'));
return 是将 yield 表达式替换成 return 语句
yield* 表达式
带星号的 yield,可以增强yield的行为,使它能够迭代一个可迭代对象,从而一次产出一个值,这也叫委托迭代。通过这样的方式,能将多个生成器连接在一起。
function * anotherGenerator(i) {
yield i + 1;
yield i + 2;
yield i + 3;
}
function * generator(i) {
yield* anotherGenerator(i);
}
var gen = generator(1);
gen.next().value; // 2
gen.next().value; // 3
gen.next().value; // 4
几个注意点:
- 任何数据结构只要有
Iterator接口,就可以被yield*遍历。 - 如果被代理的
Generator函数有return语句,那么就可以向代理它的Generator函数返回数据。
使用 yield* 实现递归算法
实现递归算法,这也是 yield* 最有用的地方,此时生成器可以产生自身。
function* nTimes(n) {
if (n > 0) {
yield* nTimes(n - 1);
yield n - 1;
}
}
for (const x of nTimes(3)) {
console.log(x);
}
// 0 1 2
上面的代码中,每个生成器首先会从新创建的生成器对象产出每个值,然后再产出一个整数。
本文内容就到这里结束了,关于生成器的核心应用异步编码模式以及回调问题,将在下篇总结。
非常感谢您的阅读,欢迎提出你的意见,有什么问题欢迎指出,谢谢!