Generato函数就是一个遍历器生成函数;Generator 函数执行后,返回一个遍历器对象。
它的Symbol.iterator属性,也是一个遍历器对象生成函数,执行后返回它自己。
与Iterator接口的关系:
任意一个对象的Symbol.iterator方法,等于该对象的遍历器生成函数,调用该函数会返回该对象的一个遍历器对象。
function* gen(){
// some code
}
var g = gen();
g[Symbol.iterator]() === g
除了for...of循环以外,扩展运算符(...)、解构赋值和Array.from方法内部调用的,都是遍历器接口(具有Iterator接口的对象)。
这意味着,它们都可以将 Generator 函数返回的 Iterator 对象,作为参数。
引用场景:
eg1:
Ajax 是典型的异步操作,通过 Generator 函数部署 Ajax 操作,可以用同步的方式表达。
function* main() {
var result = yield request("http://some.url");
var resp = JSON.parse(result);
console.log(resp.value);
}
function request(url) {
makeAjaxCall(url, function(response){
it.next(response);
});
}
var it = main();
it.next();
eg2:
利用 Generator 函数,可以在任意对象上部署 Iterator 接口。
function* iterEntries(obj) {
let keys = Object.keys(obj);
for (let i=0; i < keys.length; i++) {
let key = keys[i];
yield [key, obj[key]];
}
}
let myObj = { foo: 3, bar: 7 };
for (let [key, value] of iterEntries(myObj)) {
console.log(key, value);
}
eg3:
异步任务的封装 § ⇧
下面看看如何使用 Generator 函数,执行一个真实的异步任务。
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 函数封装了一个异步操作,该操作先读取一个远程接口,然后从 JSON 格式的数据解析信息。就像前面说过的,这段代码非常像同步操作,除了加上了yield命令。
执行这段代码的方法如下。
var g = gen();
var result = g.next();
// 由于Fetch模块返回的是一个 Promise 对象,因此要用then方法调用下一个next方法。
result.value.then(function(data){
return data.json();
}).then(function(data){
g.next(data);
});
ES6 诞生以前,异步编程的方法,大概有下面四种。
回调函数
事件监听
发布/订阅
Promise 对象
Generator 函数将 JavaScript 异步编程带入了一个全新的阶段。
网友评论