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的内容很多,我主要只是看了实现异步编程的部分......

  • 相关阅读:
    WPF DelegateCommand 出现Specified cast is not valid
    WPF DelegateCommand 出现Specified cast is not valid
    WPF DelegateCommand 出现Specified cast is not valid
    win10 sdk 是否向下兼容
    win10 sdk 是否向下兼容
    win10 sdk 是否向下兼容
    PHP extract() 函数
    PHP end() 函数
    PHP each() 函数
    PHP current() 函数
  • 原文地址:https://www.cnblogs.com/wtcsy/p/Generator.html
Copyright © 2011-2022 走看看