性能最高的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:  [email protected]

你可能感兴趣的:(JavaScript)