ES6的新语法。多种角度理解:
- 从语法上,是一个状态机,封装了多个内部状态
- 从执行结果,返回一个遍历器对象,也是一个遍历器生成函数。这个返回的结果可以依次遍历内部每个状态。
- 从执行成面,是对“协程”的实现,可以多个线程(函数)交换控制权
1 语法
1.1 形式上是普通函数,但是带有两个特征(* 和 yield)
generator函数可以不用yield语句,但是yield语句只能用在generator函数中。
函数有三个状态: world 、 girl 、return语句function* hello(){ // 函数命名带有*yield "world" // 函数体内使用yield语句 yield 翻译 产出yield "girl"return "nice"}
1.2 执行结果是一个指向内部状态的指针对象,既遍历器对象Iterator Object
let ge = hello()
1.3 调用遍历器对象的next方法,使指针移到下一个状态
既从函数头部或上次停下的地方开始执行,直到遇到下一个yield语句或retrun语句为止。
next方法返回一个对象,value属性为当前yield或return后面表达式的值,done属性为遍历器是否结束ge.nxet()// {value: "world", done: false}ge.nxet()// {value: "girl", done: false}ge.nxet()// {value: "nice", done: true}ge.nxet()// {value: undefined, done: true} //如果运行完毕,则value属性为undefined

1.3.1 yield 语句和其他语句一起使用,
理解next执行顺序以及yield暂停位置
同时与其他表达式一起,需要用括号包住
1.3.2 只有yield的执行结果
执行完yield 2后,并不知道已经执行完,调用还会继续执行,才返回done:true
1.4 next参数
yield表达式本身没有返回值,或者说总是返回undefined,
next方法可以带一个参数,作为上一条yield语句的返回值
1.5 generator生成的遍历器对象可以被for…of自动遍历,无需调用next
function* foo() {yield 1yield 2yield 3yield 4return 5}for(let v of foo()){console.log(v)}

1.6 Generator.prototype.throw()
参考
可在函数体外抛出错误,然后再generator函数体内捕获
var a = function*() {try {yield}catch(e){console.log("内部捕获" + e)}}var i = a()a.throw("a")// 内部捕获a
2 在异步操作中的应用
generator函数可以暂停执行和恢复执行,这是它能封装异步任务的更本原因。
函数体内外数据交换 + 错误处理机制 使其成为异步编程的完整解决方案。
2.1 手动控制流程
var fetch = require('node-fetch')//封装异步操作,完全是同步写法function* gen() {var url = "http://api.xxxxxx"var result = yield fetch(url)consoel.log(result)}// 执行var g = gen()// 启动异步操作var result = g.next()result.value.then((data){return data.json()}).then(function(data){// 异步操作成成功后继续向下执行,并注入异步操作结果g.next(data)})
优点: generator函数将异步操作写成同步写法,很简洁
缺点:流程管理不方便,需要手动判断何时执行第一阶段,以及后续阶段
2.2 Thunk自动控制流程
这个时候就会用到Thunk函数(只有一个参数,且这个参数为callback形式)自动执行generator函数。
//自动执行以及流程控制函数function run(fn){let gen = fn()//let result = gen.next()//if(result.done) return//result.value(function(err,data) {//let result = gen.next(data)//if(result.done) return//result.value()//})function next(err, date){let result = gen.next(data)if(result.done) returnresult.value(next)}next()}// generator函数封装的异步任务 唯一的要求是:yield后面每一个异步操作都是一个Thunk函数function* fn(){let f1 = yield readFile("fileA")let f1 = yield readFile("fileA")let f1 = yield readFile("fileA")}// 执行run(fn)
2.3 Promise自动控制
Thunk函数不是generator函数自动执行的唯一方案,关键有一种机制接受和交换程序的执行权
除了Thunk这种用回调函数,Promise对象也可以做到
唯一要求也是:yield后面是promise对象。
2.4 co模块是常用的自动执行及控制流程的通用函数工具。支持thunk和promise两种模式。
3 实际应用
在eggjs中controller中用到
