JavaScript ES6之Generator | 青训营笔记

69 阅读2分钟

这是我参与「第四届青训营 」笔记创作活动的第12天

Generator

Generator 相当于一个状态机,封装了多个内部的状态,执行Generator会返回一个遍历器对象。 Generator有两个特征:

  1. function关键字和函数名之间有一个星号 *
  2. 函数体内部使用yield表达式。
function* helloWorldGenerator() {
  yield 'hello';
  yield 'world';
  return 'ending';
}

var hw = helloWorldGenerator();

Generator函数作为一个对象的属性的时候,可以简写成如下的形式:

let obj = {
  * myGeneratorMethod() {
    ···
  }
};

遍历器对象的next()方法的运行逻辑:

  1. 遇到yield就暂停后面的操作。并将yield后面的表达式的值作为返回对象value。
  2. 如果没有遇到新的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的自动执行。