DavidSpot Blog

Developer, super curious, a dog lover, sports fan and techie guy


Publish-Subscribe pattern in javascript

If you never used a pattern like pub/sub this is very useful when you are creating a modular application and need communication between them.

A simple (yet powerfull) mini pub/sub library could be the one below:

var JSNotify = (function(){
  var topics = {};
  var hOP = topics.hasOwnProperty;

  return {
    subscribe: function(topic, listener) {
		
      // Create the topic's object if not yet created
      if(!hOP.call(topics, topic)) {
		  topics[topic] = [];
	  }

      // Add the listener to queue
      var index = topics[topic].push(listener) -1;

      // Provide handle back for removal of topic
      return {
        remove: function() {
          delete topics[topic][index];
        }
      };
    },
    notify: function(topic, info) {
		
      // If the topic doesn't exist, or there's no listeners in queue, just leave
      if(!hOP.call(topics, topic)) {
		  return;
	  }

      // Cycle through topics queue, fire!
      topics[topic].forEach(function(item) {
      		item(info != undefined ? info : {});
      });
    }
  };
})();


To subscribe do this:

var subscription = JSNotify.subscribe('pubSubDemo', function (obj) {
        console.log(obj);
    });

 

To notify the subscribers do this:

    JSNotify.notify('pubSubDemo', {
        //any argument
        hello: 'hello world' 
    });

 

To stop receiving notifications just remove:

subscription.remove();

 

If you're using Knockout you can also use the ko.subscribable function and this is very similar to the previous example:

     //create a subscriber
    var postbox = new ko.subscribable();

    //subcribe channel with topic "divChanged"
    postbox.subscribe(function (newValue) {
        console.log(newValue);
    }, this, "divChanged");

    //notify all listeners in channel "divChanged" (in this case only one) and pass some a parameter
    //I'm passing a string "div1", but you could pass anything you want
    postbox.notifySubscribers("div1", "divChanged");