您的位置:首页 > Web前端 > JavaScript

性能最高的javascript 发布订阅系统(pub/sub)Arbiter.js 源码分析

2013-01-28 20:24 676 查看
var Arbiter = (function () {
var create_arbiter = function () {
var subscriptions = {};// 订阅者
var wildcard_subscriptions = {};// 通配符队列对象
var persistent_messages = {};// 公共消息,除开特别指定(persist:false的)订阅者之外,所有订阅者都要接收此消息,即使是消息发布之后再订阅
var id_lookup = {};// 订阅者队列以索引, 供:unsubscribe和resubscribe使用
var new_id = 1;// id原子
return {
'version':'1.0'
,'updated_on':'2011-12-19'
//创建一个全新的arbiter发布订阅系统
,'create': function() { return create_arbiter(); }
//订阅
,'subscribe': function() {
var msg, messages, subscription_list, persisted_subscription_list, subscription, func, options={}, context, wildcard=false, priority=0, id, return_ids=[];
if (arguments.length<2) { return null; }
messages = arguments[0];
// Function is always last argument
// 订阅者回调总是在最后一个参数
func = arguments[arguments.length-1];
// 订阅者参数
if (arguments.length>2) { options = arguments[1] || {}; }
// 订阅者上下文
if (arguments.length>3) { context = arguments[2]; }

// 权重,值越低,越在最早执行
if (options.priority) {
priority = options.priority;
}
//分解消息类型以(topic)
if (typeof messages=="string") {
messages = messages.split(/[,\s]+/);//","或空格分割字符串
}
for (var i=0; i<messages.length; i++) {
msg = messages[i];
// If the message ends in *, it's a wildcard subscription
// 如果消息以*结尾,则认为这是一个通配符订阅
if (/\*$/.test(msg)) {
wildcard = true;
msg = msg.replace(/\*$/,'');
// 存入通配符订阅者队列
subscription_list = wildcard_subscriptions[msg];
if (!subscription_list) {
wildcard_subscriptions[msg] = subscription_list = [];
}
}
else {
// 存入订阅者队列
subscription_list = subscriptions[msg];
if (!subscription_list) {
subscriptions[msg] = subscription_list = [];
}
}
// id索引自增
id = new_id++;
// 创建订阅者对象
subscription = {'id':id,'f':func,p:priority,self:context,'options':options};
// 存入订阅者索引对象
id_lookup[id] = subscription;
// 存入订阅者队列
subscription_list.push ( subscription );
// Sort the list by priority
// 根据priority权利排序数组
subscription_list = subscription_list.sort( function(a,b) {
return (a.p>b.p?-1:a.p==b.p?0:1);
} );
// Put it back in after sorting
// 将订阅者队列存入通配符队列对象或普通队列对象
if (wildcard) {
wildcard_subscriptions[msg] = subscription_list;
}
else {
subscriptions[msg] = subscription_list;
}
// 将id存入“返回订阅者索引数组”
return_ids.push(id);

// Check to see if there are any persistent messages that need
// to be fired immediately
// 如果是参数中persist为假,并且公共消息中存在数据,则立执行订阅者回调函数,并传入对应的公共消息
if (!options.persist && persistent_messages[msg]) {/// bug? !options.persist 我觉得应该为options.persist
persisted_subscription_list = persistent_messages[msg];
for (var j=0; j<persisted_subscription_list.length; j++) {
subscription.f.call( subscription.self, persisted_subscription_list[j], {persist:true} );
}
}
}
// Return an array of id's, or just 1
// 返回一个id或者id数组,以供取消订阅时使用
if (messages.length>0) {
return return_ids;
}
return return_ids[0];
}

//发布消息
,'publish': function(msg, data, options) {
var async_timeout=10,result,overall_result=true,cancelable=true,internal_data={},subscriber, wildcard_msg;
// 通过消息类型得到订阅者列表
var subscription_list = subscriptions[msg] || [];
options = options || {};
// Look through wildcard subscriptions to find any that apply
// 循环通配符队列对象
for (wildcard_msg in wildcard_subscriptions) {
// 如果存在对应的消息类型,则将其加入订阅者列表
if (msg.indexOf(wildcard_msg)==0) {
subscription_list = subscription_list.concat( wildcard_subscriptions[wildcard_msg] );
}
}

// 如果消息类型是公共消息
if (options.persist===true) {
// 将此消息存入公共消息队列
if (!persistent_messages[msg]) {
persistent_messages[msg] = [];
}
persistent_messages[msg].push( data );
}
// 如果没有订阅者,则直接返回
if (subscription_list.length==0) {
return overall_result;
}
// 判断此消息是否可被某个订阅者阻止
if (typeof options.cancelable=="boolean") {
cancelable = options.cancelable;
}
// 循环订阅者队列
for (var i=0; i<subscription_list.length; i++) {
subscriber = subscription_list[i];
// 如果订阅者是unsubscribed状态,则跳过此订阅者继续处理下一个订阅者
if (subscriber.unsubscribed) {
continue; // Ignore unsubscribed listeners
}
try {
// Publisher OR subscriber may request async
// 如果Publisher要求或者订阅者要求异步处理订阅者回调,则采用异步方式来处理订阅者回调
if (options.async===true || (subscriber.options && subscriber.options.async)) {
// 以setTimeout实现异步
// async_timeout: 每一个订阅者回调递增延时一秒
setTimeout( (function(inner_subscriber) {
return function() {
inner_subscriber.f.call( inner_subscriber.self, data, msg, internal_data );
};
})(subscriber), async_timeout++ );
}
else {
// 如果允许订阅者取消事件传播,并且订阅者回调返回了false,则跳出循环,不再继续此消息传播
result = subscriber.f.call( subscriber.self, data, msg, internal_data );
if (cancelable && result===false) {
break;
}
}
}
catch(e) {
// 失败返回false
overall_result = false;
}
}
// 成功返回false
return overall_result;
}

// 临时取消订阅
,'unsubscribe': function(id) {
if (id_lookup[id]) {
id_lookup[id].unsubscribed = true;
return true;
}
return false;
}

// 回复订阅
,'resubscribe': function(id) {
if (id_lookup[id]) {
id_lookup[id].unsubscribed = false;
return true;
}
return false;
}

};
};
return create_arbiter();

})();


能力有限,有错误之处请指正
注:转载请注明出处:偷饭猫email: xiaodong1986@me.com
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: