0%

generator

generator简单说是一种可以控制函数内部执行状态的函数

funtion* 定义了generator函数的语法

yield定义了函数内部实现不同的状态

demo1

1
2
3
4
5
6
7
function* build(){
yield 'step1';
return 'done';
}
var generator = build();
generator.next(); //{value:'step1',done:false}
generator.next(); //{value:'done',done:true}

这里前者是函数体yield后面的值,后者代表函数是否完成

加入函数体内不包含任意一个yield,则函数只是一个延迟执行的函数而已

1
2
generator.next(); //{value:done,done:true}
generator.next(); //{value:undefined,done:true}

yield表达式还可以返回值在下一个next里调用,返回值只能通过next函数传参进来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function* build(){
yield 'step1';
var step = yield 'step2';
if(step == 3){
yield 'step3';
}else{
yield 'step4';
}
yield 'step5';
return '执行完毕!';
}
var generator = build();
console.log(generator.next(3)); // => {value: 'step1', done: false}
console.log(generator.next(3)); // => {value: 'step2', done: false}
console.log(generator.next(3)); // => {value: 'step3', done: false}
console.log(generator.next(3)); // => {value: 'step5', done: false}
console.log(generator.next(3)); // => {value: '执行完毕', done: true}

注意: next传递的参数值是传递给上一次yield表达式,所以上面例子里第三次调用next传递参数其实是把值传递给第二个yield表达式

异常处理

1
2
3
4
5
6
7
8
9
10
function* build(){
try{
throw new Error('from build');
yield 'haha';
}catch(err){
console.log('inside error'+ err);
}
}
var it = build();
it.next() // => inside error: Error: from build!

上面的例子就是在generator里面增加try…catch语句来捕获函数内部的异常,然后generator本身也提供了一个方法用于向外抛出异常

throw 此方法可以向外抛出异常,由外部的try…catch来捕获

1
2
3
4
5
6
7
8
9
10
11
12
13
function * build(){
try{
yield 'haha'; //没有抛出异常
}catch(err){
console.log('inside error: ' + err);
}
}
var it = build(); //外部的try...catch进行捕获
try{
it.throw('from it');
}catch(err){
console.log('out error: ' + err); // => out error from it
}

yield* 后面跟上别的generator实例就可以遍历别的generator里的yield了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function* build(){
var a = yield 1;
var b = yield 2;
var c = yield* child();
console.log(a, b, c);
}
function* child(){
var x = yield 3;
var y = yield 4;
console.log(x, y);
return 'child';
}

var it = build();
it.next();
it.next('a');
it.next('b');
it.next('c');
it.next('d');
// => c d
// => a b child