Generator函数【ES6】
    
      2019-03-27
    
    
  
  Generator函数【ES6】
Generator是ES6提供的一种异步执行函数。由function *定义。
一个Generator函数调用后并不立即执行,而是返回一个Iterator对象。
Generator可以理解为状态机。每次调用Iterator对象的next方法,就移动到状态机的下一个状态,并返回一个值代表状态对象,同时其内的状态(变量)保存下来。
yield表达式
yield <exp>
yield表达式标志了状态机的一个状态。调用next方法时generator函数运行逻辑如下:
- 从当前状态开始向下执行
 - 遇到yield停止,返回一个对象
{value:x, done:false},value为exp表达式计算的值 - 遇到return或执行到末尾,是为最后的状态,返回一个对象
{value:x, done:false},value的值为return表达式的值 
next方法
next()方法标志了一次状态转移,并返回一个值。yield语句像return语句一样没有值,但next()方法可以有一个参数,被当作上一条yield语句的返回值。
function *counter(){
  for(let i=0; true; i++){
    let reset = yield i;
    if(reset) {i=-1};
  }
}
var c = counter();
c.next();	//{value:0, done:false}
c.next(); //{value:1, done:false}
c.next(true); //{value:0, done:false}
for..of循环
可以用for…of循环去遍历一个generator,但这个generator要有终止状态(否则死循环)。
错误处理
Generator.prototype.throw可以在generator外抛出错误,在generator内部捕获.
function* errorHandle(){
  try{
    yield 0;
  }catch(e){
    console.log('catch',e)
  }
}
let i = errorHandle();
i.throw('a');	//注意不是全局的throw函数
//catch a
立即终止
使用Generator.prototype.return()可以立即终止一个generator
yield* 语句
将一个generator作为另一个generator的子状态机,使用yield* gene()语句
function *subFA(){
  yield '0';
  yield '1';
}
function *FA(){
  yield '2';
  yield* subFA();
  yield '3';
}
for(let state of FA()){
  console.log(state.value)
}
//输出2 0 1 3 (省略回车)
协程
除了状态机,Generator还可以理解为协程的一种实现:
- 有自己的函数栈,运行状态,堆;
 - 与线程不同,同一时间只能有一个协程占用CPU资源,其他协程处于暂停态;
 
所以Generator的出现使JS的多道(multiprogram)度提升。