搞定 koa 之generator 与 co

| |
[不指定 2017/05/17 17:29 | by 刘新修 ]

 koa 是由 tj大神利用 generator 开发的 web 框架。要理解 koa,首先要先了解 generator 与 co。作为搞定 koa 的第一篇,我们便谈谈这个。文章首发在boke.io

generator介绍

 function* Gene(){

    yield 1;

    yield 2;

}

var gene = Gene();

console.log(gene.next());//{ value: 1, done: false }

console.log(gene.next());//{ value: 2, done: false }

console.log(gene.next());//{ value: undefined, done: true }

console.log(gene.next());//Error: Generator has already finished  经@Ralph-Wang提醒从 v0.11.13 开始不抛错了,返回{ value: undefined, done: true }

从上面我们可以看到

generator 的定义和函数类似,只是在 function 后面多了一个*

调用generator 和调用函数一样,只是不像函数立即执行,而是会生成一个对象

generator 生成的对象存在一个 next 函数,调用 next 会返回 yield运算的结果对象,并停止。再次调用会在下一个 yield 处停止。

当所有的 yield 被执行完,调用 next 函数会返回{ value: undefined, done: true }。再次调用会报错

generator 与异步

 看完 generator 的介绍,你心里回想这跟异步有毛关系?不着急听我接着说

串行请求两个网页的代码

var request = require('request');

var a = {};

var b = {};

request('http://www.google.com', function (error, response, body) {

    if (!error && response.statusCode == 200) {

        a.response = response;

        a.body = body;

        request('http://www.yahoo.com', function (error, response, body) {

            if (!error && response.statusCode == 200) {

                b.response = response;

                b.body = body;

            }

        });

    }

});

我们再看看最终我们是如何利用 generator请求网页的

co(function *(){

  var a = yield request('http://google.com');

  var b = yield request('http://yahoo.com');

  console.log(a[0].statusCode);

  console.log(b[0].statusCode);

})()

上面的代码可以看到,co 里面传入了一个 generator,里面用 yield 调用异步函数。从逻辑上看,里面的异步被变成了同步。

co 到底有什么魔法?可以把我们从异步中解救出来?

想想 generator 的特性,当我们执行第一个 next 的时候,会调用第一个 request,此时我们去调用 request 的逻辑,然后把 generator 的实例穿进去。当第一个 request 逻辑完成时,在调用这个 generator 的 next,这样就到了第二个 yield 的逻辑了。当然这需要一些逻辑的封装,也就是 co 了。

根据上面的分析,我们大概可以写出下面的代码

function co(Gene){

    //先实例化一下

    var gene = Gene();

    //如果存在 next 函数

    if(gene.next){

        var fun = gene.next();//把异步函数返回过来,好继续封装

        //fun 处理完,再调用 gene.next()

        //...

    }

}

从上面的代码可以看出

yield 后面的内容需要返回一个异步函数,这样我们才可进一步封装异步处理的逻辑。

fun 需要可以传入参数,这样才可以处理多个异步

需要一个递归调用,这样才可以持续调用 next,同时根据 next 返回对象中的done属性停止逻辑

需要考虑错误处理

 今天就到这里,下一篇详细讲一下 co 的源码

NodeJs平台 | 评论(0) | 引用(0) | 阅读(3361)