Advertisement
Guest User

Untitled

a guest
Nov 26th, 2012
262
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /**
  2.  * Facility for coordinating communication between components in an event-based
  3.  * manner.
  4.  *
  5.  * <p>
  6.  * Communication is modeled by using signals.
  7.  *
  8.  * A Signal consist of a category and a payload (data). Components can publish
  9.  * signals or subscribe to signals of a certain category. When a signal is
  10.  * published, all components subscribed for the signal's category are notified.
  11.  * </p>
  12.  */
  13. function EventBus(config) {
  14.  
  15.     var log = getLogger("EventBus");
  16.  
  17.     /*
  18.      * A No-Operation function that is used to replace
  19.      * handlers when a subscription is cancelled.
  20.      */
  21.     var noop = function() {};
  22.    
  23.     /**
  24.      * key: signal category value: list of handlers subscribed for this category.
  25.      */
  26.     var subscribers = {};
  27.  
  28.     /**
  29.      * Registers a listener for a certain signal.
  30.      *
  31.      * @param category
  32.      *            The signal type
  33.      * @param handler
  34.      *            The function to be called when a signal is received.
  35.      *            
  36.      * @return A Subscription object that can be used
  37.      *          to unsubscribe from an event.  
  38.      */
  39.     this.subscribe = function(category, handler) {
  40.  
  41.         //log.info("subscribing", handler, "for", category);
  42.  
  43.         var handlerList = null;
  44.        
  45.         if (category in subscribers) {
  46.             handlerList = subscribers[category];
  47.  
  48.         } else {
  49.             handlerList = [];
  50.             subscribers[category] = handlerList;
  51.         }
  52.  
  53.         handlerList.push(handler);
  54.        
  55.         return new Subscription(category, handler);
  56.  
  57.     };
  58.    
  59.     /**
  60.      * Publishes a signal by notifying the handlers
  61.      * registered for the category.
  62.      *
  63.      * @return the number of subscribers the signal was sent to.
  64.      */
  65.     this.publish = function(category, data) {
  66.        
  67.         if (config.debug) {
  68.             log.info("publishing", category, data);
  69.         }
  70.        
  71.         if (category in subscribers) {
  72.            
  73.             var subscribersForCategory = subscribers[category];
  74.            
  75.             for (var i = 0; i < subscribersForCategory.length; i++) {
  76.                 subscribersForCategory[i](data);
  77.             }
  78.        
  79.             return subscribersForCategory.length;
  80.         }
  81.        
  82.         return 0;
  83.  
  84.     };
  85.    
  86.     /**
  87.      * <p>
  88.      * The subscription can be stored und used later by a client to
  89.      * unsubscribe a handler from an event.
  90.      * </p>
  91.      *
  92.      * For convenience, subscriptions can be "chained" by calling the
  93.      * add-method.
  94.      *  
  95.      * @returns {Subscription}
  96.      */
  97.     function Subscription(category, handler) {
  98.        
  99.         var cancelled = false;
  100.         var that = this;
  101.        
  102.         this.cancel = function() {
  103.            
  104.             if (cancelled) {
  105.                 return;
  106.             }
  107.            
  108.             log.info("unsubscribing from " + category);
  109.            
  110.             var handlerList = subscribers[category];
  111.            
  112.             if (handlerList) {
  113.                
  114.                 for (var i = 0; i < handlerList.length; i++) {
  115.  
  116.                     if (handlerList[i] === handler) {
  117.                         handlerList[i] = noop;
  118.                         cancelled = true;
  119.                         handler = null;
  120.                         return;
  121.                     }
  122.                    
  123.                 }
  124.             }
  125.            
  126.             // for safety. Make sure the subscription was found and removed.
  127.             throw "handler " + handler + " not subscribed to " + category;
  128.            
  129.         };
  130.        
  131.         /**
  132.          * Adds another subscription to this subscription.
  133.          * This is handy, when a client subscribes to multiple categories,
  134.          * and does not want to declare a separate variable for
  135.          * each subscription.
  136.          *
  137.          * <p>
  138.          * If the cancel() is invoked, all "nested" subscriptions are
  139.          * cancelled as well.
  140.          * </p>
  141.          */
  142.         this.add = function(otherSubscription) {
  143.  
  144.             var original = that.cancel;
  145.            
  146.             that.cancel = function() {
  147.                 otherSubscription.cancel();
  148.                 original.cancel();
  149.             };
  150.            
  151.         };
  152.        
  153.     }
  154.    
  155.     /**
  156.      * A facility, that can collect other subscriptions which can than
  157.      * be canceled all-at-once with one call.
  158.      * <p>
  159.      * This is handy, if client code subscribes to multiple categories,
  160.      * or if client code eventually subscribes to a category and does not
  161.      * want to check if the subscription actually did happen upon unsubscribe.
  162.      * </p>
  163.      * Example:
  164.      *
  165.      * <pre>
  166.      * var subscriptions = eventBus.newSubscriptionList();
  167.      *
  168.      * subscriptions.add(eventBus.subscribe('category1', ...);
  169.      * subscriptions.add(eventBus.subscribe('category2', ...);
  170.      *
  171.      * [...]
  172.      *
  173.      * subscriptions.cancel();
  174.      *
  175.      * </pre>
  176.      *  
  177.      */
  178.     this.nullSubscription = function() {
  179.  
  180.         var nullSubscription = {
  181.            
  182.             // do nothing
  183.             cancel: function() {},
  184.            
  185.             add: function(otherSubscription) {
  186.                 /*
  187.                  * As soon as the first "real" subscription is
  188.                  * added, replace our own cancel and add-implementation
  189.                  * with the real one.
  190.                  * All subsequent calls to add() will then be delegated to the
  191.                  * real implementation.
  192.                  */
  193.                 nullSubscription.cancel = otherSubscription.cancel;
  194.                 nullSubscription.add = otherSubscription.add;
  195.             }
  196.            
  197.         };
  198.        
  199.         return nullSubscription;
  200.        
  201.     };
  202.  
  203. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement