Generator

Generator

Generator是一种异步编程的解决方案,异步编程早期使用回调之后Promise也可以解决这个问题,而Generator也是用来解决这个问个的,但是相对于Promise会更高级一点。Generator返回的就是一个Iterator接口。

提示: index.js:126 Uncaught ReferenceError: regeneratorRuntime is not defined需要: import 'babel-polyfill'

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

Generator就是一个遍历器生成函数,所以我们直接可以把它赋值Symbol.iterator,从而使这个对象也具备这个iterator接口

``` //Generator一种新的应用 { let obj = {}; obj[Symbol.iterator] = function* (){ yield 1; yield 2 yield 3; } for(let value of obj){ console.log('value',value); } //运行结果: //value 1 //value 2 //value 3 }

>
> Generator最好是用在状态机,是JS编程中比较高级的用法,比如我们需要有a b c三种状态去描述一个事物,也就是这个事务只存在3种状态a-b b-c c-a 总之就是三种循环,永远跑不出第四种状态,用Generator函数去处理这种状态机是特别适用的```javascript

{ let state = function _(){ while(1){ yield ‘A’; yield ‘B’; yield ‘C’; } } let status = state(); /_ console.log(status.next()); //A console.log(status.next()); //B console.log(status.next()); //C console.log(status.next()); //A console.log(status.next()); //B */ setInterval(function(){ console.log(status.next()); },1000);}

{
  //async await这种写法并不是一种新的写法,只是Generator的一种语法糖
  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());
}

通过Generator实现抽奖

{
  let draw = function(count){
    //具体抽奖逻辑
    console.log(`剩余${count}次`);
  }
  let residue = function* (count){
    while(count > 0){
      count--;
      yield draw(count);
    }
  }
  let start = residue(5);
  let btn = document.createElement('button');
  btn.id = 'start';
  btn.textContent = '抽奖';
  document.body.appendChild(btn);
  document.getElementById('start').addEventListener('click',function(){
    start.next();
  },false);
}

如果服务端的某个数据状态定期的去变化,那么前端需要定时的去服务端取这个状态,因为http是无状态的链接,如果要实时的去取服务端的这种变化有两种方法,一个是长轮询,一个是通过websocket,websocket浏览器兼容性不好,因此长轮询还是一个普遍的用法一种做法是通过定时器,不断的去访问接口第二种是使用Generator

{
  //长轮询
  let ajax = function* (){
    yield new Promise(function(resolve,reject){
      //这里模拟api成功执行后 执行resolve,比如下面的{code:0},意思是返回接口成功执行后的数据
      setTimeout(function(){
        resolve({code:1})
      },200);
    });
  }

  let pull = function(){
    let generator = ajax();
    let step = generator.next(); //会返回一个promise对象实例,会对服务器端接口进行一次查询链接,上面采用setTimeout200毫秒来模拟
    //这个value就是代表了 promise实例,then是异步操作
    step.value.then(function(d){ //这个d是后端通讯的数据,这里就是上面的{code:0}
      if (d.code != 0) {
        //如果不等于 不是最新的数据,我们让每1秒钟执行一次
        setTimeout(function(){
          console.info('wait');
          pull();
        },1000)
      }else{
        //如果拿到最新数据,这里就打印出来
        console.log(d);
      }
    })
  }
  pull()
}