最高のパフォーマンスのJavascriptは購読システム(pub/sub)Abiter.jsソース分析を発表しました.
16561 ワード
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 protected]