基本概念
Generator是ES6提供的一种异步编程的解决方案。
形式上有两个特征。一是,function
关键字和函数名之间有个星号;二是,函数内部使用yield
语句,定义不同的内部状态。
function* helloGenerator(){
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloGenerator();
必须调用对象的next
方法,使得指针移向下一个状态。Generator
函数是分段执行的。yield
语句是暂停执行的标记,而next
方法可以恢复执行。
hw.next()
// { value: 'hello', done: false }
hw.next()
// { value: 'world', done: false }
hw.next()
// { value: 'ending', done: true }
hw.next()
// { value: undefined, done: true }
yield语句
遍历器对象的next
方法的运行逻辑如下:
(1)遇到yield
语句,就暂停执行后面的操作,并将紧更着yield
后面表达式的值,作为返回的对象value
的属性值。
(2)下次调用next方法时,再继续往下执行,直到遇到下一个yield
语句的。
(3)如果没有遇到新的yield
语句,就一直运行到函数结束,直到return
语句为止,并将return
语句后面的表达式的值,作为返回的对象的value
值。
(4)如果该函数没有return
语句,则返回的对象的value
属性值为undefined
。
Generator函数可以不用yield语句,这时就变成一个单纯的暂缓执行函数。
function* f(){
console.lof('execute');
}
var generator = f();
setTimeout(function(){
generator.next();
},2000);
上面代码如果f
是普通函数,再为变量generator
赋值的时候就已经执行了。但是,函数f
是一个Generator
函数,就变成只有调用next
方法时,函数f
才会执行。
另外注意,yield
语句不能再普通函数里面,否则会报错。
Generator.prototype.return()
return
方法可以返回指定的值,并终结了Generator
函数。
function* gen(){
yield 1;
yield 2;
yield 3;
}
var g = gen();
g.next(); //{value:1,done:false}
g.return('foo'); //{value:"foo",done:true}
g.next(); //{value:undefined,done:true}
如果Generator
函数内部有try ... finally
代码块,那么return
方法会推迟到finally
代码块执行完成再执行。
function* numbers(){
yield 1;
try{
yield 2;
yield 3;
} finally{
yield 4;
yield 5;
}
yield 6;
}
var g = numbers()
g.next(); //{value:1,done:false}
g.next(); //{value:2,done:false}
g.return(7);//{value:4,done:false}
g.next();//{value:5,done:false}
g.next();//{value:7,done:true}