这是我参与「第四届青训营 」笔记创作活动的第12天
Generator
Generator 相当于一个状态机,封装了多个内部的状态,执行Generator会返回一个遍历器对象。 Generator有两个特征:
- function关键字和函数名之间有一个星号 *
- 函数体内部使用yield表达式。
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator();
Generator函数作为一个对象的属性的时候,可以简写成如下的形式:
let obj = {
* myGeneratorMethod() {
···
}
};
遍历器对象的next()方法的运行逻辑:
- 遇到yield就暂停后面的操作。并将yield后面的表达式的值作为返回对象value。
- 如果没有遇到新的yield就执行到函数结束,并将return的表达式的值作为返回对象。如果没有return则返回undefined。
ES6提供了yield* 表达式,用于在一个Generator里执行另一个Generator。
function* bar() {
yield 'x';
yield* foo();
yield 'y';
}
// 等同于
function* bar() {
yield 'x';
for (let v of foo()) {
yield v;
}
yield 'y';
}
for (let v of bar()){
console.log(v);
}
Generator函数的异步应用
异步简单地说是一个任务不是连续完成的,先执行了第一段,转而去完成其他任务,然后再回来执行第二段。
整个Generator函数就是一个封装的异步任务,异步操作需要暂停的额地方,都用yield语句来注明。
示例:
var fetch = require('node-fetch');
function* gen(){
var url = 'https://api.github.com/users/github';
var result = yield fetch(url);
console.log(result.bio);
}
在上面这段代码中,Generator封装了一个异步操作,先读取一个github的远程接口,然后从JSON获取数据的解析信息。这段代码的执行方法如下:
var g = gen();
var result = g.next();
result.value.then(function(data){
return data.json();
}).then(function(data){
g.next(data);
});
首先执行了Generator函数,获取遍历器对象,然后使用next()执行异步任务的四一阶段,因为是一个Promise对象,因此使用then()来调用下一个next()方法。
Thunk函数
将一个参数放入一个临时函数(Thunk函数)中,再将这个临时函数传入函数体。
一般来说只要函数有回调函数,就能写成Thunk函数的形式。当然还可以用Thunkify模块来实现Thunk函数。 Thunk函数可以自动执行Generator函数。
co模块
co 模块也可以实现Generator的自动执行。