Generator 函数
Generator 是 JS 模拟协程在 ES6 的实现,最大特点是可以交出函数的执行权(暂停执行)
function* gen(x) {
  var y = yield x + 2;
  return y;
}
var g = gen(1);
g.next(); // { value: 3, done: false }
g.next(); // { value: undefined, done: true }
- 整个 Generator 函数是一个封装的异步任务容器
    - 异步需要暂停的地方使用 yield 语句注明
- 函数名之前加 * 是和普通函数的区别
 
- 调用 Generator 函数,会返回一个内部指针(遍历器) g
    - Generator 区别于普通函数的另一个地方是执行它不会返回结果,返回的是指针对象
- 调用指针 g 的 next 方法,会移动内部指针指向第一个遇到 yield 语句(上例是执行到 x+2)
- 每次调用 next 方法,会返回一个对象,表示当前阶段的信息(value,done)
        - value 属性是 yield 语句后面表达式的值,表示当前阶段的值
- done 属性是一个布尔值,表示 Generator 函数是否执行完毕,是否还有下一个阶段
 
 
Generator 函数的数据交换和错误处理
- Generator 能够暂停和恢复执行,这是它能封装异步任务的根本原因。
- 除此之外它还有个特性:函数体外的数据交换和错误处理机制
    - next 方法返回值的 value 属性是 Generator 函数向外输出数据
- next 方法还能接收参数,向内输入数据
 
function* gen(x) {
  var y = yield x + 2;
  return y;
}
var g = gen(1);
g.next(); // { value: 3, done: false }
g.next(2); // { value: 2, done: true }
- 第一个 next 方法的 value 属性,返回表达式 x+2 的值为(3)
- 第二个 next 方法带有参数 2,这个参数作为上个阶段异步任务的结果被变量 y 接收,因此 value 的属性值返回的就是 2 (变量 y 的值)
Generator 可以部署错误处理,捕捉函数体外抛出的错误
function* gen(x) {
  try {
    var y = yield x + 2;
  } catch (e) {
    console.log(e);
  }
  return y;
}
var g = gen(1);
g.next();
g.throw("出错了");
// 出错了
- 在 generator 函数体外,使用指针对象的 throw 方法抛出错误,可以被函数体内的 try catch 代码块捕获。
- 
    这意味着,出错的代码与处理错误的代码,实现了时间和空间上的分离 
 
线程和携程的区别
- 
    实现方式 - 线程通常是系统实现的(也有语言模拟的,如 Python 的线程)
- 携程通常是库实现的(也有语言实现的,如 Go)
 
- 
    控制权 - 线程控制权通常是系统控制,是被动的
- 携程的控制通常是调用方主动控制的(需要 yield 释放控制权)
 
- 
    态的切换 - 由于线程是系统控制,通常切换需要进入内核态进行处理
- 携程通常是在用户态就完成了切换
- 携程切换是在一个线程内进行的
 
参见