zoukankan      html  css  js  c++  java
  • 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的内容很多,我主要只是看了实现异步编程的部分......

  • 相关阅读:
    Physics Experiment POJ3684
    FLIPTILE POJ NO.3279
    [蓝桥杯][算法提高VIP]盾神与积木游戏
    棋盘问题
    出栈次数的DFS计算
    Bribe the Prisoners
    Crazy Rows
    关于部分“记录”密码获取^o^/
    NOIP2017爆炸记
    【luogu 1024 一元三次方程求解】二分思想
  • 原文地址:https://www.cnblogs.com/wtcsy/p/Generator.html
Copyright © 2011-2022 走看看