Generator函数

Generator函数解决异步编程的方案

  • 回调是异步编程的早期解决方式
  • Promise也是解决异步编程的
  • Generator函数显得更高级一些,next,yield*是Generator函数的一部分,遇到yield就会有停止,如果要进行下一步的话要调用next

{
  // genertaor基本定义 ,genertaor返回的就是一个Iterator接口
  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}
}

{
    // Generator函数和Iterator接口的关系
    // 任意一个对象的Generator函数都是部署在Symbol.iterator这个属性上,从而这个对象有了Iterator接口
    // Generator函数就是一个遍历器生成函数,使用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编程中比较高级的用法
    let state=function* (){
        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());
    
    //结果
    {"value":"A","done":false}
    {"value":"B","done":false}
    {"value":"C","done":false}
    {"value":"A","done":false}
    {"value":"B","done":false}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

ES7中asyns,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());
 }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

实例

{
  // 抽奖的逻辑和次数的分离开的,
  let draw=function(count){
    //具体抽奖逻辑
    console.info(`剩余${count}次`)
  }

  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)
}

{
  // 长轮询
  let ajax=function* (){
    yield new Promise(function(resolve,reject){
      setTimeout(function () {
        resolve({code:0})
      }, 200);
    })
  }

  let pull=function(){
    let genertaor=ajax();
    let step=genertaor.next();
    // 这个value就是Promise实例
    step.value.then(function(d){
      if(d.code!=0){
        setTimeout(function () {
          console.info('wait');
          pull()
        }, 1000);
      }else{
        console.info(d);
      }
    })
  }

  pull();
  
  // 如果服务端返回的code不是0,那么就会一直去轮训,
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55