注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

snoopyxdy的博客

https://github.com/DoubleSpout

 
 
 

日志

 
 

AsyncProxy,摆脱node.js异步代码嵌套难阅读(机制不同的山寨版eventproxy)  

2011-09-22 16:39:23|  分类: node |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
之前我们分析过JacksonTian(http://weibo.com/shyvo)写的eventproxy.js,前后端都可以正常使用。写的是相当巧妙,今天正好空闲,借于JacksonTian大师的启发,写了一个山寨版本的eventproxy,当练练手。不过这个AsyncProxy只能用于node.js服务端哦。
先贴AsyncProxy.js源代码,回去再放在github上了:
AsyncProxy.js的实现机制是依靠node.js的emitter事件触发来做的,和eventproxy.js相比有如下不同:
1、支持链式调用,什么是链式调用呢?比如“异步1”、“异步2”,如果"异步2"需要用到"异步1"返回的数据,则必须等待"异步1"返回以后再开始异步2。对于这样耦合度高的异步请求完全支持,可以很方便的取到上一步,或者上几步的数据。
2、增加异步返回状态,能够在每次异步请求返回后,知道当前已经返回异步请求数和总共需要返回请求数,方便查找系统的瓶颈。
3、没有eventproxy.js的always功能,只有eventproxy.js的once功能。
4、gc需要手动处理,没有eventproxy.js自动gc。

GITHUB源码和测试用例以及示例地址:https://github.com/DoubleSpout/node.js---AsyncProxy

var events =  require("events");
module.exports =  AsyncProxy = function(ischain){
this.emitter = new events.EventEmitter();
this.eventname = 'AsyncProxy';
this.data = [];
this.ischain = ischain||false; //是否链式调用,默认是false
}
AsyncProxy.prototype.addlistener = function(){ //建立事件监听函数
var ap = this;
ap.emitter.on(ap.eventname,function(order, data){
ap.prev = ap.data[order] = data;
if(--ap.length===0){
ap.callback(ap.data);
ap.emitter.removeAllListeners(ap.eventname);
}
})
}
AsyncProxy.prototype.rec = function(order, data){ //当异步返回入口
this.emitter.emit(this.eventname, order, data); 
if(this.ischain && ++order<this.asyncs.length){ this.asyncs[order](order);}
return {total:this.asyncs.length, rec:this.asyncs.length - this.length}
}
AsyncProxy.prototype.ap = function(){ //主入口
var ap = this, i=0, len = arguments.length - 1;
ap.asyncs = [].slice.apply(arguments, [0, len]); //将参数eventname1-n转存成events 数组
    ap.callback = arguments[len];
ap.addlistener();
if((ap.length=ap.asyncs.length)&&!ap.ischain){ //如果非链式调用
while(i++ < ap.asyncs.length){ ap.asyncs[i-1](i-1);}
}
else ap.asyncs[0](0);
return ap.asyncs.length;
}

代码很简单,30多行,基本实现原理同eventproxy.js一样,站在巨人的肩膀上肯定能轻松不少哇~~
我们上测试代码:

var AsyncProxy = require('./asyncproxy.js');
var as = new AsyncProxy(true); //这里设置true,表示链式调用
  var Client1 = require("redis").createClient(); //建立3个redis连接
  var Client2 = require("redis").createClient();
  var Client3 = require("redis").createClient();
var f1 = function(order){  //异步函数1,注意这里需要传递一个参数order或者其他任何名字,代表他的序列
setTimeout(function(){   //我们这只异步函数1经过1秒再触发
Client1.get('test', function(err, reply){
console.log('f1 is ok‘)    //当异步1回来以后
var x = as.rec(order,reply);  //注意:这里的order必须于上面参数名相同,可以任意自定义,reply代表异步1返回结果
console.log('已经返回:'+x.rec+'/'+x.total)  //这里会输出“已经返回:1/3”
Client1.quit(); //关闭redis 连接1
})
},1000)
}
var f2 = function(order){
setTimeout(function(){
Client2.get(as.prev, function(err, reply){
 //注意:这里的as.prev表示上一个返回结果,
//这里返回结果为'test1',所以异步操作2就根据异步操作1的返回值去做get('test1')了
console.log('f2 is ok, 前一个数据内容:'+as.prev)  //或者使用as.data[n]来获取前几个的值
var x = as.rec(order, reply);
console.log('已经返回:'+x.rec+'/'+x.total)
Client2.quit();
})
},500)
}
var f3 = function(order){
Client3.get('test2', function(err, reply){
console.log('f3 is ok, 前一个数据内容:'+as.prev)
var x  =as.rec(order, reply);
console.log('已经返回:'+x.rec+'/'+x.total)
Client3.quit();
})
}
var all = function(data){ //设置完成回调函数,这里返回的data是一个数组 “ [ 异步1返回数据, 异步2返回数据, 异步3返回数据 ] ”
var d = ''
for(var i=0;i<data.length;i++){
d += data[i]+' ### '
}
console.log(d);
as=null; //用完以后将as设置为null,这里需要手动gc
}
var total = as.ap(f1, f2, f3, all);  //as.ap是入口,参数规则  异步函数1, 异步函数2 。。。 回调函数
console.log('需要返回的异步处理数: '+total) //这里输出3

最后输出结果:
AsyncProxy,摆脱node.js异步代码嵌套难以阅读(机制不同的山寨版eventproxy) - snoopyxdy - snoopyxdy的博客
 
非链式的测试这里就不做了,非链式as.prev这个意义就不大了。
  评论这张
 
阅读(2275)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2016