ECMAScript6--17.Generator

2017-10-24  本文已影响47人  飞菲fly

1.Generator

2.generator返回的就是一个iterator接口;

通过next的方式不断去做函数体内部的几个阶段,执行tell的时候,会遇到第一个yield的时候停下来,执行完了yield之前的语句,调用next的时候会执行第一个yield;在执行next的时候,会执行到下一个yield或者return,以此类推,从而保证了这个函数体内部看上去是一个异步操作的过程;

generator基本定义:

    {
      let tell = function*(){
      yield 'a';
      yield 'b';
      return 'c'
    };
   
     let k = tell();
   
     console.log(k.next());
     console.log(k.next());
     console.log(k.next());
     console.log(k.next());
     //打印结果:
    Object{value:"a",done:false}
    Object{value:"b",done:false}
    Object{value:"c",done:true}
    Object{value:undefined,done:true}

    }

3.generator函数和iterator接口的关系;

4.什么情况下generator有这最大的优势呢?

{
    //状态机
    let state =function*(){
        //while(1)永远循环
        while(1){
            yield 'A';
            yield 'B';
            yield 'C';
        
        }
    };

    let status = state();
    console.log(status.next());
    console.log(status.next());
    console.log(status.next());
    console.log(status.next());
    console.log(status.next());
    //输出结果:
    Object{value:"A",done:false}
    Object{value:"B",done:false}
    Object{value:"B",done:false}
    Object{value:"A",done:false}
    Object{value:"B",done:false}

}

5.async

{
    let state =async function(){
        while(1){
            await 'A';
            await 'B';
            await 'C';
        
        }
    };

    let status = state();
    console.log(status.next());
    console.log(status.next());
    console.log(status.next());
    console.log(status.next());
    console.log(status.next());
    //输出结果:
    Object{value:"A",done:false}
    Object{value:"B",done:false}
    Object{value:"B",done:false}
    Object{value:"A",done:false}
    Object{value:"B",done:false}

}

6.什么时候用generator可以发挥强大的作用
eg:抽奖次数限制;
* 当前用户还可以抽奖5次;用户点击一次,抽奖变4次...1次,抽奖剩余逻辑,前端要做限制,服务端也要做;
好处:次数没有保存到全局变量中,通过初始化直接给generator传一个参数进去,让它不断的循环和业务的状态点,从而达到一个抽奖的次数限制和状态的变化;

    {
        //显示:抽奖逻辑这块;剩余5次,当点了抽奖按钮的时候,这个过程
        要执行抽奖的逻辑,随机过程,到哪个奖品上;还要显示当前剩余几次;
        //draw这个函数实现的是集体抽奖逻辑和当前剩余次数的显示;
        let draw =function(count){
            //具体抽奖逻辑
            //怎么计算当前还有多少次呢?
            --之前的做法:设一个全局的变量来保存当前的次数,这样非常不安全的;
              别人知道你的变量是什么,直接修改你的变量,都拦不住了;
              尽量少把数据存放在全局对象上,影响页面性能;
            console.info(`剩余${count}次`);
        };
        
        let residue =function*(count){
            //判断count是不是大于0,大于0还可以抽奖
            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('star').addEventListener('click',function(){
            star.next();
        },false);
        
    }

7.长轮询

    {
        //长轮询;模拟ajax一个过程
        //这个ajax表示对接口的模拟;
        let ajax = functon* (){
            yield new Promise(function(resolve,reject){
                //模拟请求的耗时;用定时器模拟一下;
                //真实的环境中,setTimeout重写,写成真实的接口;在接口的成回调中,把
resolve写一下,就可以直接拿来用了;
                setTimeout(function(){
                    //接口成功返回了,执行resolve;比如最后返回的状态接口code:0;
                    resolve({code:0});
                    //resolve({code:1});会不断的轮询;
                },200);
            });
        };
        
        //轮询的过程;执行后端通信一次;
        let pull =function(){
            //对generator实例化;
            let generator = ajax();
            //取得当前generator的步骤,next相当于让generator进行了一次运行; 这个地方会
运行第一个的yield,返回一个promise实例,这个promise实例,对后端通信服务端接口进行一次连接,
查询一次;这里通过延时 200ms来表达200ms进行一次通信,然后接下一步;
            let step = generator.next();
            
        //value是promise实例,通过then异步操作,拿到d表示拿后端通信的数据,就是{code:0};        
            step.value.then(function(d){
                //判断如果数据拿到的是最新的;!=0就不是新的,要再一次的请求;
              if(d.code!=0){
                //每一秒钟请求一次;
                setTimeout(function(){
                    //查询中
                    console.info('wait');
                    pull();
                },1000);
              }else{
                //如果拿到最新数据,长轮询查询结束;直接把数据打出来;
                console.info(d);
              
              }  
            
            });
        };
        
        //相当于进行了一次轮询,因为{code:0}就查询了一次;
        pull();//Object{code:0}
        //{code:1}会每隔1200ms都是在输出wait,一直在进行一个长轮询的查询;
    }
上一篇 下一篇

猜你喜欢

热点阅读