Generator生成器

2019-10-11  本文已影响0人  royluck

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 异步编程带入了一个全新的阶段。

上一篇 下一篇

猜你喜欢

热点阅读