美文网首页
es6学习笔记整理(十五)Generator生成器

es6学习笔记整理(十五)Generator生成器

作者: 尤樊容 | 来源:发表于2018-03-14 13:43 被阅读103次
    基本概念

    Generator函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同。
    Generator函数有多种理解角度。从语法上,首先可以把它理解成,Generator函数一个状态机,封装了多个内部状态。
    执行Generator函数会返回一个遍历器对象,也就是说,Generator函数除了状态机,还是一个遍历器对象生成函数。
    形式上,Generator函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号,二是,函数体内部使用yield语句,定义不同的内部状态。(yield语句在英语里的意思就是“产出”)

    next函数的用法
    let tell = function* (){
        yield 'a';
        yield 'b';
        return 'c'
    };
    
    let k = tell();
    
    console.log(k.next());//{value: "a", done: false}
    console.log(k.next());//{value: "b", done: false}
    console.log(k.next());//{value: "c", done: true}
    console.log(k.next());//{value: undefined, done: true}
    

    调用第一个next,会去执行第一个yield,调用第二个next,会去执行第二个yeild,
    以此类推,函数体内部是个异步调用的过程

    yield*的语法

    使用genertor也可以作为遍历器的返回值

            let obj = {};
            obj[Symbol.iterator] = function* (){
                yield 1;
                yield 2;
                yield 3;
            };
    
            for(let value of obj){
                console.log(value);//1 2 3
            }
    
    高级用法,状态机

    generator特别适用的情况

            let state = function* (){
                while(1){
                    yield 'A';
                    yield 'B';
                    yield 'C';
                }
            }
            let status = state();
            console.log(status.next());//{value: "A", done: false}
            console.log(status.next());//{value: "B", done: false}
            console.log(status.next());//{value: "C", done: false}
            console.log(status.next());//{value: "A", done: false}
            console.log(status.next());//{value: "B", done: false}
            console.log(status.next());//{value: "C", done: false}
            console.log(status.next());//{value: "A", done: false}
    

    以上的例子中,无论你连续调用多少次.next(),done的值都不可能是true,会一直循环打印。
    还有一种async形式的,但是浏览器需要添加兼容包才可识别,所有的功能和方法的使用都和上面的一样,结果也一样。反正先写下来,做一个提示:

    let state = async function (){
        while(1){
            await 'A';
            await 'B';
            await 'C';
        }
    }
    let status = state();
    console.log(status.next());//{value: "A", done: false}
    console.log(status.next());//{value: "B", done: false}
    console.log(status.next());//{value: "C", done: false}
    console.log(status.next());//{value: "A", done: false}
    console.log(status.next());//{value: "B", done: false}
    console.log(status.next());//{value: "C", done: false}
    console.log(status.next());//{value: "A", done: false}
    
    使用实例1

    有一个例子,看看实际如何运用。
    以下例子中,实现前端抽奖剩余次数限制,使用generator做判断

    let draw = function (count) {
        //具体业务逻辑
        console.info(`剩余${count}次`)
    };
    
    //计算剩余次数,原来使用的是全局变量,现在通过generator来进行判断
    let residue = function* (count){
        while (count>0){
            count--;
            yield draw(count);
        }
    };
    let star = residue(5);
    let btn = document.createElement('button');
    btn.id = 'start';
    btn.textContent = '抽奖';
    document.body.appendChild(btn);
    document.getElementById('start').addEventListener('click', function (){
        star.next();
    },false);
    
    使用实例2

    长轮循:服务端某一个数据状态定期的变化,前端需要获取时,除了webSocket,还常轮循,由于webSocket的浏览器兼容不好,所以长轮循还是很常用的,之前的做法是使用定时器定时的发送请求,现在通过generator来实现。

    let ajax = function* (){
        yield new Promise(function(resolve, reject){
            //这里应该写请求,现在使用定时器代替
            setTimeout(function (){
                resolve({code:0});
            },200);
        });
    };
    
    let pull = function (){
        let generator = ajax();
        let step = generator.next();
        step.value.then(function(d){
            if(d.code != 0){
                setTimeout(function (){
                    console.log('wait');
                    pull();
                },1000);
            }else{
                console.log(d);//{code: 0}
            }
        });
    };
    pull();
    

    相关文章

      网友评论

          本文标题:es6学习笔记整理(十五)Generator生成器

          本文链接:https://www.haomeiwen.com/subject/icfofftx.html