<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[刘新修]]></title> 
<link>http://liuxinxiu.com:80/index.php</link> 
<description><![CDATA[刘新修的个人博客 (Liuxinxiu'S Blog)]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[刘新修]]></copyright>
<item>
<link>http://liuxinxiu.com:80/generator_co/</link>
<title><![CDATA[搞定 koa 之generator 与 co]]></title> 
<author>刘新修 &lt;admin@yourname.com&gt;</author>
<category><![CDATA[NodeJs平台]]></category>
<pubDate>Wed, 17 May 2017 09:29:07 +0000</pubDate> 
<guid>http://liuxinxiu.com:80/generator_co/</guid> 
<description>
<![CDATA[ 
	<p>&nbsp;<span style="color: rgb(51, 51, 51); font-family: &quot;Helvetica Neue&quot;, &quot;Luxi Sans&quot;, &quot;DejaVu Sans&quot;, Tahoma, &quot;Hiragino Sans GB&quot;, STHeiti, sans-serif; font-size: 15px; white-space: pre-wrap;">koa 是由 tj大神利用 generator 开发的 web 框架。要理解 koa，首先要先了解 generator 与 co。作为搞定 koa 的第一篇，我们便谈谈这个。文章首发在</span><a href="http://boke.io/" target="_blank" style="color: rgb(0, 136, 204); text-decoration: none; font-family: &quot;Helvetica Neue&quot;, &quot;Luxi Sans&quot;, &quot;DejaVu Sans&quot;, Tahoma, &quot;Hiragino Sans GB&quot;, STHeiti, sans-serif; font-size: 15px; white-space: pre-wrap;">boke.io</a></p><p>generator介绍</p><p>&nbsp;function* Gene()&#123;</p><p>&nbsp; &nbsp; yield 1;</p><p>&nbsp; &nbsp; yield 2;</p><p>&#125;</p><p>var gene = Gene();</p><p>console.log(gene.next());//&#123; value: 1, done: false &#125;</p><p>console.log(gene.next());//&#123; value: 2, done: false &#125;</p><p>console.log(gene.next());//&#123; value: undefined, done: true &#125;</p><p>console.log(gene.next());//Error: Generator has already finished &nbsp;经@Ralph-Wang提醒从 v0.11.13 开始不抛错了，返回&#123; value: undefined, done: true &#125;</p><p>从上面我们可以看到</p><p>generator 的定义和函数类似，只是在 function 后面多了一个*</p><p>调用generator 和调用函数一样，只是不像函数立即执行，而是会生成一个对象</p><p>generator 生成的对象存在一个 next 函数，调用 next 会返回 yield运算的结果对象，并停止。再次调用会在下一个 yield 处停止。</p><p>当所有的 yield 被执行完，调用 next 函数会返回&#123; value: undefined, done: true &#125;。再次调用会报错</p><p>generator 与异步</p><p>&nbsp;看完 generator 的介绍，你心里回想这跟异步有毛关系？不着急听我接着说</p><p>串行请求两个网页的代码</p><p>var request = require('request');</p><p>var a = &#123;&#125;;</p><p>var b = &#123;&#125;;</p><p>request('http://www.google.com', function (error, response, body) &#123;</p><p>&nbsp; &nbsp; if (!error &amp;&amp; response.statusCode == 200) &#123;</p><p>&nbsp; &nbsp; &nbsp; &nbsp; a.response = response;</p><p>&nbsp; &nbsp; &nbsp; &nbsp; a.body = body;</p><p>&nbsp; &nbsp; &nbsp; &nbsp; request('http://www.yahoo.com', function (error, response, body) &#123;</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!error &amp;&amp; response.statusCode == 200) &#123;</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b.response = response;</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b.body = body;</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#125;</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &#125;);</p><p>&nbsp; &nbsp; &#125;</p><p>&#125;);</p><p>我们再看看最终我们是如何利用 generator请求网页的</p><p>co(function *()&#123;</p><p>&nbsp; var a = yield request('http://google.com');</p><p>&nbsp; var b = yield request('http://yahoo.com');</p><p>&nbsp; console.log(a[0].statusCode);</p><p>&nbsp; console.log(b[0].statusCode);</p><p>&#125;)()</p><p>上面的代码可以看到，co 里面传入了一个 generator，里面用 yield 调用异步函数。从逻辑上看，里面的异步被变成了同步。</p><p>co 到底有什么魔法？可以把我们从异步中解救出来？</p><p>想想 generator 的特性，当我们执行第一个 next 的时候，会调用第一个 request，此时我们去调用 request 的逻辑，然后把 generator 的实例穿进去。当第一个 request 逻辑完成时，在调用这个 generator 的 next，这样就到了第二个 yield 的逻辑了。当然这需要一些逻辑的封装，也就是 co 了。</p><p>根据上面的分析，我们大概可以写出下面的代码</p><p>function co(Gene)&#123;</p><p>&nbsp; &nbsp; //先实例化一下</p><p>&nbsp; &nbsp; var gene = Gene();</p><p>&nbsp; &nbsp; //如果存在 next 函数</p><p>&nbsp; &nbsp; if(gene.next)&#123;</p><p>&nbsp; &nbsp; &nbsp; &nbsp; var fun = gene.next();//把异步函数返回过来，好继续封装</p><p>&nbsp; &nbsp; &nbsp; &nbsp; //fun 处理完，再调用 gene.next()</p><p>&nbsp; &nbsp; &nbsp; &nbsp; //...</p><p>&nbsp; &nbsp; &#125;</p><p>&#125;</p><p>从上面的代码可以看出</p><p>yield 后面的内容需要返回一个异步函数，这样我们才可进一步封装异步处理的逻辑。</p><p>fun 需要可以传入参数，这样才可以处理多个异步</p><p>需要一个递归调用，这样才可以持续调用 next，同时根据 next 返回对象中的done属性停止逻辑</p><p>需要考虑错误处理</p><p>&nbsp;今天就到这里，下一篇详细讲一下 co 的源码</p>
]]>
</description>
</item><item>
<link>http://liuxinxiu.com:80/generator_co/#blogcomment</link>
<title><![CDATA[[评论] 搞定 koa 之generator 与 co]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://liuxinxiu.com:80/generator_co/#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>