给迭代器传递参数
迭代器向外传值:
- 在生成器内部使用
yield
语句返回值。 - 给迭代器的
next()
传递参数,则这个参数会替代生成器中一条yield
语句的返回值
function *createIterator() {
let first = yield 1;
let second = yield first + 2;
yield second + 3;
}
let iterator = createIterator();
iterator.next(); //"{ value: 1, done: false}"
iterator.next(4); //"{ value: 6, done: false }"
iterator.next(5); //"{ value: 8, done: false}"
iterator.next(); //"{ value: undefined, done: true}"
注意点
- 第一次调用
next()
方法时传参是无效的,因为next()
方法的参数是替代上一次yield
语句的返回值。 - 每次执行
next()
方法时,执行完赋值右边的yield
之后就会暂停,直到下一次next()
才会执行前一个yield
语句的赋值。
在迭代器中抛出错误
迭代器不仅提供了 next()
方法传参,还提供了 throw()
方法抛出错误。通过 throw()
方法,当迭代器恢复执行时可令其抛出一个错误,然后中断后续代码的执行。
iterator.throw(new Error('Boom'))
可以在代码块内部使用 try-catch
捕获这些错误,使得就算出现错误,也可以继续向下执行。
在迭代器内,如果使用了 yield
语句,可以通过 next()
和 throw()
控制执行过程,也可以使用 return
语句返回一些不一样的内容。
生成器返回语句
在生成器中,return
表示操作完成,其后的语句都不会执行,所以会将 done
属性置为 true
,将 value
属性置为 return
的返回值,没有返回值为 undefined
。
function *createIterator() {
yield 1;
return 42;
yield 2;
}
let iterator = createIterator();
iterator.next(); //"{ value: 1, done: false}"
iterator.next(); //"{ value: 42, done: true}"
iterator.next(); //"{ value: undefined, done: true}"
通过 return
指定的返回值,只会在返回对象中出现一次,在后续调用中,value
会被重置为 undefined
。
委托生成器
合并两个生成器
合并两个生成器,只需要新建一个生成器,然后将这两个生成器的 name
放在其中的 yield
后面即可,中间需要加上星号。
function *createCombinediterator() {
yield *createiterator1();
yield *createiterator2();
yield 'hello';
yield *'hello';
}
这里的 createCombinediterator
生成器先后委托了 createiterator1
和 createiterator2
两个生成器。
这里值得注意的是,
yield 'hello'
在调用 next() 时会返回 hello 这个字符串。而yield *'hello'
会调用 hello 这个字符串的默认迭代器,也就是一个字符一个字符的返回。
异步任务执行
我们希望每隔 1000ms 输出1、2、3,但又不想多层回调函数嵌套使用,就可以使用生成器来简化。
function task(gen){
let iterator = gen();
result = iterator.next();
function step(){
setTimeout(() => {
if(!result.done){
result = iterator.next();
step();
}
}, 1000);
}
step();
}
function* gen(){
console.log(1);
yield;
console.log(2);
yield;
console.log(3);
}
function task3() {
console.log(6);
}
task(gen);