Generator

学异步的解决方案,然后看到了Generator,很好的东西,记录下!


一些好的文章

Generator概念

yield语句

next方法的参数

如何优雅的实现异步编程了


一些好的文章

http://es6.ruanyifeng.com/#docs/generator

http://es6.ruanyifeng.com/#docs/async

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/yield


Generator概念

Generator函数有多种理解角度。从语法上,首先可以把它理解成,Generator函数是一个状态机,封装了多个内部状态。

执行Generator函数会返回一个遍历器对象,也就是说,Generator函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历Generator函数内部的每一个状态。

形式上,Generator函数是一个普通函数,但是有两个特征。一是,function命令与函数名之间有一个星号;二是,函数体内部使用yield语句,定义不同的内部状态(yield语句在英语里的意思就是“产出”)。


yield语句

由于Generator函数返回的遍历器对象,只有调用next方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield语句就是暂停标志。

遍历器对象的next方法的运行逻辑如下

function* example(){
    var a = 1,
        b = 2,
        c = 3;
    console.log(a);
    yield a;
    console.log(b)
    yield b;
    console.log(c);
    yield c;
    console.log(a+b+c);
    return a+b+c;
}

var result = example(); //这里执行完后函数里面的代码并不会执行
result.next();   //开始执行函数里面的代码 打印a的值 遇到第一个yield 返回里面的值 {value: 1, done: false}
result.next();   //打印b的值 遇到第二个yield 返回里面的值 {value: 2, done: false}
result.next();   //打印c的值 遇到第三个yield 返回里面的值 {value: 3, done: false}
result.next();   //打印a+b+c的值 返回 {value: 3, done: false}

关于yield 要仔细记录一些东西

yield

yield 关键字用来暂停和继续一个生成器函数

语法

yield [[expression]];

用作返回值. 如果忽略, 将返回 undefined .

这个可以是表达式 yield a+b;也可以是函数 yield function(fun){fun(a+b)}

ps: 在看co源码的时候,用到的就是函数的方式,但是相关的介绍就比较少了

描述

yield 关键字使生成器函数暂停执行,并返回跟在它后面的表达式的当前值. 可以把它想成是 return 关键字的一个基于生成器的版本.

yield 关键字实际返回一个对象,包含两个属性, value 和 done. value 属性为 yield expression 的值, done 是一个布尔值用来指示生成器函数是否已经全部完成.

一旦在yield expression 处暂停, 除非外部调用生成器的 next() 方法,否则生成器的代码将不能继续执行. 这使得可以对生成器的执行以及渐进式的返回值进行直接控制.

yiled语句是表达式的例子很多了,介绍也很多,当为函数的时候就很少,主要记录下

1.当表达式为函数的时候,调用next返回的是没有value的

2.yield的函数的第一个参数(是个函数), 通过next的返回值调用value方法来设置,

一个例子来说明

function* fun(){
    yield function(callback){
        console.log(callback.toString());
    }
}
var result = fun();
var step   = result.next();  //返回的值{done: false}  没有value值  但是有个value这个方法
console.log(step.value)     //可以看到确实有这个方法
step.value(function(){var str = "测试!!"})  //调用这个方法  参数传一个函数进去  返现这个函数当做参数传到了yield表达式的函数里面去了
//所以 后面就打印了这个函数

next方法的参数

yield句本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield语句的返回值.

一个例子来说明上面这段话的意思

function* arg(){
    var a = yield 1;
    console.log(a);
    var c = yield 3;
    console.log(c);
}
var r = arg();
r.next();
r.next();                //打印的undefined  因为a的值不是 yield里面表达式的值
r.next("your sister");   //打印your sister 因为next参数的值才是yield返回的值

如何优雅的实现异步编程了

在解决异步编程的解决方案里面,promise回调模式写成了链式结构,并且解决了串行和并行请求的方案,总之很好,浏览器支持有些也支持,不支持jquery也有类似的用法,总之很好就是了, 貌似唯一的一个缺点就是还是回调方式的.

Generator了,可以写成非回调方式的,但是在浏览器中支持不好,nodejs中却很好用,伟大的co

一个简单例子看怎么进行异步处理的

function get(url){
    return function(callback) {
        $.ajax({
            url      : url,
            type     : "get",
            dataType : "html",
            success : function(response){
                callback(response);
            }
        });
    }
}


function *ansyc(){
    var html1 =  yield get("http://www.cnblogs.com/aggsite/SideRight");
    html1 = html1.slice(0,20) +"截取部分11111-------------------------------------------";
    console.log(html1)
    var html2 =  yield get("http://www.cnblogs.com/aggsite/UserStats");
    html2 = html2.slice(0,20) +"截取部分2222-------------------------------------------";
    console.log(html2);
    var html3 =  yield get("http://www.cnblogs.com/aggsite/AggStats");
    html3 = html3.slice(0,20) +"截取部分3333-------------------------------------------";
    console.log(html3);
}


var result = ansyc();
var step   = result.next()
step.value(function(res){
    var step1 = result.next(res);
    step1.value(function(res1){
        var step2 = result.next(res1); 
        step2.value(function(res2){
            var step3 = result.next(res2); 
        });
    })
});

只看ansyc里面函数的部分,可以说阅读代码起来是非常的顺畅的,如果把下面的一大段异步回调封装一下调用,就可以实现优雅的异步编程了

function co(generator) {
    var gen = generator();
    function next(result) {
        var step = gen.next(result);
        if (!step.done) {
            step.value(next);
        }
    }
    next();
}

function get(url){
    return function(callback) {
        $.ajax({
            url      : url,
            type     : "get",
            dataType : "html",
            success : function(response){
                callback(response);
            }
        });
    }
}

co(function* (){
    var html1 =  yield get("http://www.cnblogs.com/aggsite/SideRight");
    html1 = html1.slice(0,20) +"截取部分11111-------------------------------------------";
    console.log(html1)
    var html2 =  yield get("http://www.cnblogs.com/aggsite/UserStats");
    html2 = html2.slice(0,20) +"截取部分2222-------------------------------------------";
    console.log(html2);
    var html3 =  yield get("http://www.cnblogs.com/aggsite/AggStats");
    html3 = html3.slice(0,20) +"截取部分3333-------------------------------------------";
    console.log(html3);
})

这样看起来确实很舒服了,代码还很少了,不过没有提供错误的处理方式

一切看起来那么美好,但是在浏览器上面支持的非常糟糕,nodejs端到时很不错的方案.浏览器端可以用wind.js才实现


PS:Generator的内容很多,我主要只是看了实现异步编程的部分......

原文地址:https://www.cnblogs.com/wtcsy/p/Generator.html