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 功能实现参数回传,让代码看起来非常‘同步’,让异步体验变的更加友好。

  • 相关阅读:
    mysql的安装
    一个电脑登录多个微信
    项目工程构建
    MYSQL 添加字段
    Centos 搭建maven私服
    Nacos 动态刷新@RefreshScope
    Cookie & Session
    阿里蚂蚁 笔试题
    springboot 将配置文件中的配置读取为properties配置类
    .Net Gacutil工具(全局程序集缓存工具)使用教程
  • 原文地址:https://www.cnblogs.com/52cik/p/generator-co.html
Copyright © 2011-2022 走看看