秒杀 tj/co 的 hprose 协程库

来源:互联网 发布:淘宝客qq群哪里有引流 编辑:程序博客网 时间:2024/05/17 22:15

首先,tj/co 库中的 yield 只支持 thunk 函数,生成器函数,promise 对象,以及数组和对象,但是不支持普通的基本类型的数据,比如 null, 数字,字符串等都不支持。这对于 yield 一个类型不确定的变量来说,是很不方便的。而且这跟 await 也是不兼容的。

其次,在 yield 数组和对象时,tj/co 库会自动对数组中的元素和对象中的字段递归的遍历,将其中的所有的Promise 元素和字段替换为实际值,这对于简单的数据来说,会方便一些。但是对于带有循环引用的数组和对象来说,会导致无法获取到结果,这是一个致命的问题。即使对于不带有循环引用结构的数组和对象来说,如果该数组和对象比较复杂,这也会消耗大量的时间。而且这跟 await 也是不兼容的。

再次,对于 thunk 函数,tj/co 库会认为回调函数第一个参数必须是表示错误,从第二个参数开始才表示返回值。而这对于回调函数只有一个返回值参数的函数,或者回调函数的第一个参数不表示错误的函数来说,tj/co 库就无法使用了。

而 hprose.co 对 yield 的支持则跟 await 完全兼容,支持对所有类型的数据进行 yield

当 hprose.co 对 chunk 函数进行 yield 时,如果回调函数第一个参数是 Error 类型的对象才会被当做错误处理。如果回调函数只有一个参数且不是 Error 类型的对象,则作为返回值对待。如果回调函数有两个以上的参数,如果第一个参数为 null 或 undefined,则第一个参数被当做无错误被忽略,否则,全部回调参数都被当做返回值对待。如果被当做返回值的回调参数有多个,则这多个参数被当做数组结果对待,如果只有一个,则该参数被直接当做返回值对待。

下面我们来举例说明一下:

yield 基本类型

首先我们来看一下 tj/co 库的例子:

var co = require('co');co(function*() {    try {        console.log(yield Promise.resolve("promise"));        console.log(yield function *() { return "generator" });        console.log(yield new Date());        console.log(yield 123);        console.log(yield 3.14);        console.log(yield "hello");        console.log(yield true);    }    catch (e) {        console.error(e);    }});

该程序运行结果为:

promisegeneratorTypeError: You may only yield a function, promise, generator, array, or object, but the following object was passed: "Sat Nov 19 2016 14:51:09 GMT+0800 (CST)"    at next (/usr/local/lib/node_modules/co/index.js:101:25)    at onFulfilled (/usr/local/lib/node_modules/co/index.js:69:7)    at process._tickCallback (internal/process/next_tick.js:103:7)    at Module.runMain (module.js:577:11)    at run (bootstrap_node.js:352:7)    at startup (bootstrap_node.js:144:9)    at bootstrap_node.js:467:3

其实除了前两个,后面的几个基本类型的数据都不能被 yield。如果我们把上面代码的第一句改为:

var co = require('hprose').co;

后面的代码都不需要修改,我们来看看运行结果:

promisegenerator2016-11-19T06:54:30.081Z1233.14hellotrue

也就是说,hprose.co 支持对所有类型进行 yield 操作。下面我们再来看看 async/await 是什么效果:

(async function() {    try {        console.log(await Promise.resolve("promise"));        console.log(await function *() { return "generator" });        console.log(await new Date());        console.log(await 123);        console.log(await 3.14);        console.log(await "hello");        console.log(await true);    }    catch (e) {        console.error(e);    }})();

上面的代码基本上就是把 co(function*...) 替换成了 async function...,把 yield 替换成了 await

我们来运行上面的程序,注意,对于当前版本的 node 运行时需要加上 --harmony_async_await 参数,运行结果如下:

promise[Function]2016-11-19T08:16:25.316Z1233.14hellotrue

我们可以看出,await 和 hprose.co 除了对生成器的处理不同以外,其它的都相同。对于生成器函数,await 是按原样返回的,而 hprose.co 则是按照 tj/co 的方式处理。也就是说 hprose.co 综合了 await 和 tj/co 的全部优点。使用 hprose.co 比使用 await 或 tj/co 都方便。

0 0