Generator
Generator 函数是一个普通函数。
区别:
- function关键字与函数名之间有一个星号。(ES6 没有规定,function关键字与函数名之间的星号,写在哪个位置都能通过。)
- 函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”)。
- 调用 Generator 函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象,也就是遍历器对象(Iterator Object)。必须调用遍历器对象的 next() 方法,使得指针移向下一个状态
function * helloWorldGenerator() {
yield console.log('hello');
yield console.log('world');
return console.log('ending');
}
var hw = helloWorldGenerator();
— 控制台输入 hw.next();
hw.next();
index.html:156 hello
hw.next();
index.html:157 world
hw.next();
index.html:158 ending
必须调用遍历器对象的 next() 方法,使得指针移向下一个状态。每次调用next方法,内部指针就从上一次停下来的地方开始执行,直到遇到下一个yield表达式(或return语句)为止。
换言之,Generator 函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行。
上面代码定义了一个 Generator 函数helloWorldGenerator,它内部有两个yield表达式(hello和world),即该函数有三个状态:hello,world 和 return 语句(结束执行)。
yield 表达式
由于 Generator 函数返回的遍历器对象,只有调用next方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield表达式就是暂停标志。
next方法
(1)遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。
(2)下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。
(3)如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的属性值。
(4)如果该函数没有return语句,则返回的对象的value属性值为undefined。
yield表达式后面的表达式,只有当调用next方法、内部指针指向该语句时才会执行,因此等于为 JavaScript 提供了手动的“惰性求值”(Lazy Evaluation)的语法功能。
用途:
ajax的异步处理,需要等待别的异步成功后再执行
function* main() {
...
var result = yield request("http://www.xxx.com?rows=10&f={firstName}");
console.log(result);
//do 别的ajax请求;
}
co 是什么
co是用来自动执行generator函数的工具。generator的好处是可以在定义函数时候就打上“断点”,调用函数时候可以在断点的地方暂停函数的执行。Generator带来的问题是如何控制什么时候进行下一步调用。co可以解决这个问题。
特点:
1、co 模块,它基于 ES6 的 generator 和 yield ,能用同步的形式编写异步代码的nodejs模块。
代码如下:
const co = require ('co');
function* main() {
执行代码。。。
});
co(main);
co 模块可以将异步解改成同步。co 函数接受一个 generator 函数作为参数,在函数内部自动执行 yield 。
co实现generator自动执行的条件
需要yield后面的数据类型为:
- promises
- thunks (functions)
- array (parallel execution)
- objects (parallel execution)
- generators (delegation)
- generator functions (delegation)
最后两种类型是官方建议避免使用的。
使用:
安装:
$ npm install co
index.js
function* helloWorldGenerator() {
var a = Promise.resolve(1);
var b = Promise.resolve(2);
var c = Promise.resolve(3);
var res = yield [a, b, c];
console.log(res);
}
co(helloWorldGenerator).catch(onerror);
// 执行: [1, 2, 3]
function onerror(err) {
console.error(err);
}