Generator

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

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

  1. {
  2. let tell = function* (){
  3. yield 'a';
  4. yield 'b';
  5. return 'c';
  6. }
  7. let t = tell();
  8. console.log(t.next());
  9. console.log(t.next());
  10. console.log(t.next());
  11. //Object {value: "a", done: false}
  12. //Object {value: "b", done: false}
  13. //Object {value: "c", done: true}
  14. }

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

  1. //Generator一种新的应用
  2. {
  3. let obj = {};
  4. obj[Symbol.iterator] = function* (){
  5. yield 1;
  6. yield 2
  7. yield 3;
  8. }
  9. for(let value of obj){
  10. console.log('value',value);
  11. }
  12. //运行结果:
  13. //value 1
  14. //value 2
  15. //value 3
  16. }

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

  1. ```javascript
  2. {
  3. //async await这种写法并不是一种新的写法,只是Generator的一种语法糖
  4. let state = async function(){
  5. while(1){
  6. await 'A';
  7. await 'B';
  8. await 'C';
  9. }
  10. }
  11. let status = state();
  12. console.log(status.next());
  13. console.log(status.next());
  14. console.log(status.next());
  15. console.log(status.next());
  16. console.log(status.next());
  17. }

通过Generator实现抽奖

  1. {
  2. let draw = function(count){
  3. //具体抽奖逻辑
  4. console.log(`剩余${count}次`);
  5. }
  6. let residue = function* (count){
  7. while(count > 0){
  8. count--;
  9. yield draw(count);
  10. }
  11. }
  12. let start = residue(5);
  13. let btn = document.createElement('button');
  14. btn.id = 'start';
  15. btn.textContent = '抽奖';
  16. document.body.appendChild(btn);
  17. document.getElementById('start').addEventListener('click',function(){
  18. start.next();
  19. },false);
  20. }

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

  1. {
  2. //长轮询
  3. let ajax = function* (){
  4. yield new Promise(function(resolve,reject){
  5. //这里模拟api成功执行后 执行resolve,比如下面的{code:0},意思是返回接口成功执行后的数据
  6. setTimeout(function(){
  7. resolve({code:1})
  8. },200);
  9. });
  10. }
  11. let pull = function(){
  12. let generator = ajax();
  13. let step = generator.next(); //会返回一个promise对象实例,会对服务器端接口进行一次查询链接,上面采用setTimeout200毫秒来模拟
  14. //这个value就是代表了 promise实例,then是异步操作
  15. step.value.then(function(d){ //这个d是后端通讯的数据,这里就是上面的{code:0}
  16. if (d.code != 0) {
  17. //如果不等于 不是最新的数据,我们让每1秒钟执行一次
  18. setTimeout(function(){
  19. console.info('wait');
  20. pull();
  21. },1000)
  22. }else{
  23. //如果拿到最新数据,这里就打印出来
  24. console.log(d);
  25. }
  26. })
  27. }
  28. pull()
  29. }