zoukankan      html  css  js  c++  java
  • 让 Generator 自启动

    文章同步自个人博客:http://www.52cik.com/2016/07/11/generator-co.html

    此前只是简单使用而没有真正的去研究 Generator,这次要好好折腾下这货。

    异步编程

    对于 jser 来说,异步非常熟悉了吧,但是真正理解异步的却不多,因为大部分人只知道回调。
    随着js的快速发展,异步方案也层出不穷,从最开始的回调到Promise,再到Generator,然后到async/await。
    甚至有人说 async/await 是异步的终极解决方案,我不敢直接赞同,只能说是目前最好的异步体验。
    本篇先从 Generator 讲起,后序再详细说 async/await。

    从回调开始

    从最最经典的 ajax 请求开始今天的话题吧。
    假如,我们要依次请求 url1, url2, url3 这3个地址。

    $.get('url1', function(r1) {
      $.get('url2', function(r2) {
        $.get('url3', function(r3) {
          console.log(r1, r2, r3);
        });
      });
    });
    

    一不小心就写成这样了。
    如果你是 jQuery 粉的话,你可能会说也可以这样实现啊。

    $.get('url1').then(function(r1) {
      console.log(r1);
      return $.get('url2');
    }).then(function(r2) {
      console.log(r2);
      return $.get('url3');
    }).then(function(r3) {
      console.log(r3);
    });
    

    用 jQuery 的 Deferred 对象,类似 Promise 来规避回调地狱,看着确实平了,但体验并不是特别友好。

    用 Generator 来和谐回调

    Generator 的基础这里就不展开说了,直接说应用。

    function* gen() {
      var r1 = yield $.get('url1');
      var r2 = yield $.get('url2');
      var r3 = yield $.get('url3');
    
      console.log(r1, r2, r3);
    }
    

    这是比较友好的异步方式,但是还有个至关重要的因素,怎么运行这个 Generator 是个问题。
    直接手动 g.next() 运行那肯定不行,鬼知道有多少个 yield。
    我们要实现一个启动器来运行它,并把 Promise 结果传给下一次next,这样就实现了 yield 接收值的功能。

    先来实现一个最简陋的起动器。

    function run(gen) {
      var g = gen();
    
      function next(d) {
        var r = g.next(d);
        r.done || r.value.then(function(d){ next(d) }); // 这个是关键,把值传回传
      }
    
      next();
    }
    

    然后我们只要一行代码。

    run(gen);
    

    Generator 就启动起来了,并且一直执行到 done 为 true 为止。

    真实例子

    打开 http://www.52tian.net/ 动漫网。非广告,确实没找到合适的测试站,凑合下吧。
    然后把下面代码贴到控制台,看下结果。如果执行不了,请升级浏览器,本例在 chrome 51 下通过。

    function* gen() {
      var r1 = yield $.get('/json/anime/4126.htm');
      var r2 = yield $.get('/json/anime/11129.htm');
      var r3 = yield $.get('/json/anime/427.htm');
    
      console.log([r1, r2, r3].join('
    '));
    }
    
    function run(gen) {
      var g = gen();
    
      function next(d) {
        var r = g.next(d);
        r.done || r.value.then(function(d){ next(d) }); // 这个是关键,把值传回传
      }
    
      next();
    }
    
    run(gen);
    

    小结

    可能你已经发现了,其实这就是 co 的原理,但 co 比这个例子严谨多了,而且api设计的也非常友好。
    本篇到此也就结束了,利用 Generator 的 yield 功能实现参数回传,让代码看起来非常‘同步’,让异步体验变的更加友好。

  • 相关阅读:
    uva 408 Uniform Generator
    Java实现 蓝桥杯VIP 算法提高 栅格打印问题
    Java实现 蓝桥杯VIP 算法提高 栅格打印问题
    Java实现 蓝桥杯VIP 算法提高 栅格打印问题
    Java实现 蓝桥杯VIP 算法提高 打水问题
    Java实现 蓝桥杯VIP 算法提高 打水问题
    Java实现 蓝桥杯VIP 算法提高 打水问题
    Java实现 蓝桥杯VIP 算法提高 打水问题
    Java实现 蓝桥杯VIP 算法提高 不同单词个数统计
    Java实现 蓝桥杯VIP 算法提高 不同单词个数统计
  • 原文地址:https://www.cnblogs.com/52cik/p/generator-co.html
Copyright © 2011-2022 走看看