性能最高的javascript 发布订阅系统(pub/sub)Arbiter.js 源码分析
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