Skip to content
小马哥 edited this page Nov 19, 2016 · 28 revisions

基本用法

ES6 中引入了 GeneratorGenerator 通过封装之后,可以作为协程来进行使用。

其中对 Generator 封装最为著名的当属 co,但是 co 跟 ES2016 的 async/await 相比的话,还存在一些比较严重的缺陷。

hprose 中也引入了对 Generator 封装的协程支持,而且比 tj 的 co 更加完善,后面我们会详细介绍它们之间的一些差别。

下面先让我们来看一个例子:

var hprose = require('hprose');

hprose.co(function*() {
    var client = hprose.Client.create('http://hprose.com/example/');
    yield client.useService();
    console.log(yield client.hello("World"));
});

hprose.co(也可以是 hprose.Future.co)就是一个协程封装函数。它的功能是以协程的方式来执行生成器函数。该方法允许带入参数执行。

在上面的例子中,client 是一个 Hprose 的 HTTP 客户端。Hprose 的 JavaScript 版本(包括 NodeJS, HTML5, JavaScript微信小程序专用版)的客户端为异步客户端,所以它上面的调用都是异步调用。

因为 JavaScript 的 Proxy(中文版) 具有浏览器兼容性问题,所以在客户端代理对象的生成上,使用的是动态获取服务列表的方式来实现的。

上面的 yield client.useService() 语句就是用于返回这个客户端代理对象,使用默认参数调用时,会将 client 对象本身设置为代理对象,因此这里我们没有使用返回值,如果要在其它地方使用的话,最好是保存它的返回值。

client.useService() 的返回值是一个 Promise 对象,如果不使用协程,那么在使用时,需要使用 then 方法,然后在其回调中才能使用,而使用协程,直接使用 yield 就可以获得实际的代理对象了。而且因为在这里 client 本身就是代理对象,因此当 yield 返回代理对象之后,client 对象就已经被初始化好了,因此后面就可以直接调用 client 上的 hello 方法了。

clienthello 方法的返回值也是个 Promise 对象,使用 yield 之后,它的返回值就变成了实际值,也就可以直接用 console.log 进行打印了。

通过上面的例子,我们可以看出,使用协程方式,Hprose 调用就被完全同步化了。这可以大大简化异步程序的编写。

协程兼容性问题

因为 Generator 是在 ES6 中引入了,所以比较老版本的 NodeJS 是不支持的,而浏览器的支持就更少了,目前只有 Chrome 和 Firefox 支持,而 IE、Opera、Safari 都不支持,HyBird App 也不支持。

那是否意味着这个功能很鸡肋呢?并不是,因为现在有许多工具可以将 ES6 代码转换为 ES5 代码,比如 Babel。其中就包括对 Generator 的支持。所以,即使你使用了协程,仍然可以通过这些转换器转换为在各种浏览器中都可以运行的程序。

为了方便用户使用,在 hprose 中还直接集成了 regenerator-runtime.js,不需要额外引入这个文件了。

微信小程序因为缺少全局对象,仍然需要使用:

const regeneratorRuntime = require("regenerator-runtime.js");

的方式来单独引入该文件,不过该文件也已经放在微信小程序专用版中了,免去了用户单独寻找该文件的麻烦。

Clone this wiki locally