{ Publisher Subscriber Pattern }

A few weeks ago I was introduced to the Publisher Subscriber pattern in JS, pretty much confused by the methodology behind it I decided to give it a go.

The publisher subscriber pattern allows several methods to subscribe to a particular event. Methods and functions can unsubscribe and subscribe to any event at will, this is handy if you want to remove or add a method to an event handler at runtime.

For example, we would normally do something like this in jQuery

  1.  
  2. $('.button').click(function(i){
  3.       doFoo();
  4.      doBar();
  5. });
  6.  

This can get pretty messy especialy if we later decide to add new methods to the event handler. We can irradicate this by introducing publisher subscriber.

  1.  
  2. var buttonPublisher = new Publisher();
  3. var fooFn = function(el){};
  4. var barFn = function(el){};
  5.  
  6. buttonPublisher.subscribe(fooFn);
  7. buttonPublisher.subscribe(barFn);
  8.  
  9. $('.button').click(function(i){
  10.       buttonPublisher.notify(this);
  11. });
  12.  

This in effect stops you from needing to add or remove functions within event handlers, and keeps them clean and tidy. One line of code replaces several. This isn't the main benefit of the publisher subscriber pattern though, the beauty of this pattern becomes apparent when you need to unsubscribe a method based on the outcome of another event.

  1.  
  2. $('.removeFoo').click(function(i){
  3. buttonPublisher.unsubscribe(fooFn)
  4. });
  5.  

Can you see where I'm coming from now? To achieve this without the publisher subscriber pattern you would need to set up a boolean and check to see whether you can perform an action, or create multiple click event handlers, which can get pretty nasty if you have quite a few things you need to do, it's just as bad as writing onclick="doFoo(); doBar(); doFoo1(); doBar1()" in your html.

I've done all of the hard work for you, this is a pretty basic publisher subscriber class.

  1.  
  2. /**
  3.  * @author gwilliams
  4.  */
  5. var Publisher = function(){
  6.  
  7.     var _subscribers = [];
  8.  
  9.     return {
  10.  
  11.         /*
  12.          * Pushes the subscribers callback function into
  13.          * the private _subscribers property.
  14.          */
  15.         subscribe: function(fn){
  16.             _subscribers.push(fn);
  17.         },
  18.  
  19.         /*
  20.          * Method is used to unsubscribe a subscribers callback function
  21.          * from the publisher.
  22.          */
  23.         unsubscribe: function(fn){
  24.  
  25.             _newSubscribers = []; // Create an empty subscriber array
  26.  
  27.             /*
  28.              * Loop through the _subscribers array, checking to see
  29.              * whether the function in 'fn' matches any function in
  30.              * the _subscribers array, if it doesn't match, push it
  31.              * in the _newSubscribers array.
  32.              */
  33.             for (var i = 0; i < _subscribers.length; i++) {
  34.                 if (_subscribers[i] !== fn) {
  35.                     _newSubscribers.push(fn);
  36.                 }
  37.             }
  38.  
  39.             /*
  40.              * Now the _newSubscribers array only contains the callback
  41.              * methods we want we can re-assign it to the private
  42.              * _subscribers property.
  43.              */
  44.             _subscribers = _newSubscribers;
  45.         },
  46.  
  47.         /*
  48.          * Wipes the subscriber list
  49.          */
  50.         wipe: function(){
  51.  
  52.             _subscribers = [];
  53.  
  54.         },
  55.  
  56.         /*
  57.          * Returns all of the current subscribers in an array
  58.          */
  59.         getSubscribers: function(){
  60.             return _subscribers;
  61.         }
  62.  
  63.         /*
  64.          * The notify method is used to invoke all of the callback methods
  65.          * in the _subscribers array, o is the property to be sent to the
  66.          * subscriber method, this can be anything from a string to an object
  67.          * or even JSON.
  68.          */
  69.         notify: function(o){
  70.              for (var i = 0; i < _subscribers.length; i++) {
  71.                 _subscribers[i].call(o);
  72.             }
  73.         }
  74.  
  75.     }
  76.  
  77. };
  78.  

Tags: , ,

This entry was posted on Thursday, July 24th, 2008 at 2:29 pm and is filed under Design Patterns, Javascript. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

One Response to “{ Publisher Subscriber Pattern }”

Nick September 4th, 2008 at 7:57 am

I really like this example, and it is something I will have to consider implementing in the future. I’m constantly having to do stuff like this for my clients, so any little bit to help me wrap my mind around it helps.

Leave a Reply