让 Generator 自启动

代码棱镜客
• 阅读 2667

文章同步自个人博客: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('\n'));
}

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

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Karen110 Karen110
4年前
一篇文章带你了解JavaScript日期
日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用
待兔 待兔
1年前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
待兔 待兔
4年前
【Golang】Golang + jwt 实现简易用户认证
<p本文已同步发布到我的个人博客:<ahref"https://links.jianshu.com/go?tohttps%3A%2F%2Fglorin.xyz%2F2019%2F11%2F23%2FGolangjwtsimpleauth%2F"target"_blank"https://glorin.xyz/2019/11/23/Golang
Stella981 Stella981
3年前
SpringBoot:使用小技巧合集
!(https://oscimg.oschina.net/oscnet/9568359ee35c42c391a2061b9e5ed793.jpg)本文转自公众号一枚趔趄的猿作者:謝謝同学个人博客:http://blog.lqdev.cn前言最近工作比较忙,事情也比较多。加班回到家都十点多了,洗
Stella981 Stella981
3年前
Exceptionless
<divid"cnblogs\_post\_body"class"blogpostbodycnblogsmarkdown"<h1id"exceptionless.netcore开源日志框架"Exceptionless.NetCore开源日志框架</h1<blockquote<p作者:markjiang7m2<b
Wesley13 Wesley13
3年前
Activiti 工作流入门指南
<divclass"htmledit\_views"id"content\_views"<h1<aname"t0"</a概览</h1<p如我们的介绍部分所述,Activiti目前分为两大类:</p<ul<li<p<ahref"https://activiti.gitbook.io/activiti7deve
Stella981 Stella981
3年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Stella981 Stella981
3年前
Python基础教程,Python入门教程(非常详细)
<divclass"htmledit\_views"id"content\_views"<p<ahref"http://c.biancheng.net/python/base/"rel"nofollow"第1章Python编程基础</a</p<p1.<ahref"http://c.biancheng.net/view/
Wesley13 Wesley13
3年前
CSS 奇思妙想:超级酷炫的边框动画
点上方蓝字关注公众号「前端从进阶到入院」精选原创好文助你进入大厂文章转载自公众号「iCSS前端趣闻」今天逛博客网站shoptalkshow\1\,看到这样一个界面,非常有意思:!(https://oscimg.oschina.net/oscnet/9655b35af5a045999ff55c144a3f7c