晴明的博客园 GitHub      CodePen      CodeWars     

[ES6] Generator(生成器)

#

生成器

 

 

function*

function* name([param[, param[, ... param]]]) { statements }

声明(function关键字后跟一个星号)定义一个generator(生成器)函数,返回一个Generator对象。

也可以用GeneratorFunction构造器和function* expression定义一个generator函数。

生成器是一种可以从中退出并在之后重新进入的函数。
生成器的环境(绑定的变量)会在每次执行后被保存,下次进入时可继续使用。

调用一个生成器函数并不马上执行它的主体,而是返回一个这个生成器函数的迭代器(iterator)对象。
当这个迭代器的next()方法被调用时,生成器函数的主体会被执行直至第一个yield表达式,该表达式定义了迭代器返回的值,或者,被 yield*委派至另一个生成器函数。
next()方法返回一个对象,该对象有一个value属性,表示产出的值,和一个done属性,表示生成器是否已经产出了它最后的值。

#

            function* idMaker() {
                var index = 0;
                while (index < 3)
                    yield index++;
            }
            var gen = idMaker();
            console.log(gen.next().value); // 0
            console.log(gen.next().value); // 1
            console.log(gen.next().value); // 2
            console.log(gen.next().value); // undefined

#

            function* anotherGenerator(i) {
                yield i + 1;
                yield i + 2;
                yield i + 3;
            }

            function* generator(i) {
                yield i;
                yield * anotherGenerator(i);
                yield i + 10;
            }
            var gen = generator(10);
            console.log(gen.next().value); // 10
            console.log(gen.next().value); // 11
            console.log(gen.next().value); // 12
            console.log(gen.next().value); // 13
            console.log(gen.next().value); // 20

 #yield命令是异步两个阶段的分界线。
协程遇到yield命令就暂停,等到执行权返回,再从暂停的地方继续往后执行。

function *asnycJob() {
  // ...其他代码
  var f = yield readFile(fileA);//执行到此处,执行权将交给其他协程。
  // ...其他代码
}

#

    function* gen(x) {
        var y = yield x + 2;
        return y;
    }

    var g = gen(1);
    console.log(g.next()); // { value: 3, done: false }
    console.log( g.next(2)); // { value: 2, done: true }

#

var fetch = require('node-fetch');

function* gen(){
  var url = 'https://api.github.com/users/github';
  var result = yield fetch(url);
  console.log(result.bio);
}

var g = gen();
var result = g.next();//Fetch模块返回的是一个Promise对象

result.value.then(function(data){
  return data.json();
}).then(function(data){
  g.next(data);
});

#

var fetch = require('node-fetch');

function* gen(){
  var url = 'https://api.github.com/users/github';
  var result = yield fetch(url);
  console.log(result.bio);
}

var g = gen();
var result = g.next();//Fetch模块返回的是一个Promise对象

result.value.then(function(data){
  return data.json();
}).then(function(data){
  g.next(data);
});

 

 

 

 

Generator.prototype.next()

gen.next(value)

next() 方法返回一个包含属性 done 和 value 的对象.

该方法也可以通过接受一个参数用以向生成器传值.

#使用 next()方法

   function* gen() {
        yield 1;
        yield 2;
        yield 3;
    }

    var g = gen(); // "Generator { }"
    console.log(g);

    // "Object { value: 1, done: false }"
    console.log(g.next());

    // "Object { value: 2, done: false }"
    console.log(g.next());

    // "Object { value: 3, done: false }"
    console.log(g.next());
    
    // "Object { value: undefined, done: true }"
    console.log(g.next());

#调用 next 方法并传入了参数

    function* gen() {
        while(true) {
            var value = yield null;
//首次调用 next 方法时没有出任何输出, 这是因为初始状态时生成器通过yield 返回了null.
            console.log(value);//2
        }
    }

    var g = gen(); // "Generator { }"
    console.log(g);

    // "Object {value: null, done: false}"
    console.log(g.next(1));

    // "Object {value: null, done: false}"
    console.log(g.next(2));

 

 

Generator.prototype.return()

gen.return(value)

return() 方法返回给定的值并结束生成器.

 

#使用 return()方法

    function* gen() {
        yield 1;
        yield 2;
        yield 3;
    }

    var g = gen(); // "Generator { }"
    console.log(g.next());        // { value: 1, done: false }
    console.log(g.return("foo")); // { value: "foo", done: true }
    console.log(g.next());        // { value: undefined, done: true }

 

 

Generator.prototype.throw()

gen.throw(exception)

throw() 方法用来向生成器抛出异常.

#使用 throw()

    function* gen() {
        while (true) {
            try {
                yield 42;
            } catch (e) {
                console.log("Error caught!");
            }
        }
    }

    var g = gen();
    console.log(g.next()); // { value: 42, done: false }
    
    console.log(g.throw(new Error("Something went wrong"))); 
    // "Error caught!"
    //Object {value: 42, done: false}

 

 

GeneratorFunction(生成器函数)

new GeneratorFunction ([arg1[, arg2[, ...argN]],] functionBody)

GeneratorFunction构造器生成新的generator function 对象。
在JavaScript中,生成器函数实际上都是GeneratorFunction的实例对象

#GeneratorFunction并不是一个全局对象。可以通过下面的代码获取。

Object.getPrototypeOf(function*(){}).constructor

#

var GeneratorFunction = Object.getPrototypeOf(function*(){}).constructor
var g = new GeneratorFunction("a", "yield a * 2");
var iterator = g(10);
console.log(iterator.next().value); // 20

 

function* expression (function*表达式)

function* [name]([param1[, param2[, ..., paramN]]]) {
   statements
}

function*关键字可以在表达式内部定义一个生成器函数。

function*表达式和function* 声明比较相似,并具有几乎相同的语法。
function*表达式和function*声明之间主要区别就是函数名,即在创建匿名函数时,function*表达式可以省略函数名

#定义了一个未命名的生成器函数并把它赋值给x,函数产出(yield)它的传入参数的平方

var x = function*(y) {
   yield y * y;
};

 

 

 

 



posted @ 2016-05-23 11:39  晴明桑  阅读(241)  评论(0编辑  收藏  举报