Gal Segal's Blog

Thoughts of a programmer with a soul

Jan 2

Javascript Library Neutral Pub-Sub

Tags:

Mobius_Wave_by_SaTaNiA

In the past few weeks I’m trying  to create a lean JavaScript infrastructure. One of the ideas that came to my mind was the notion of “Pub-Sub“: the ability to subscribe to some event that fires from one module, and react in another module, without these two modules should know about each other.

Of course, this is not a new idea, and if you read my post about the  JavaScript Modules Infrastructure, this is another approach to the same problem: how to manage a large scale web application with a lot of JavaScript involved.

The “Pub-Sub” solution involves the idea of one object (the “broker“) in the window level, that handles all the subscriptions and publishing of events: when a module act because a user clicked on a button, it notifies the broker, and the broker notifies all other objects that were subscribed to this event.

So, few important points:

  1. The broker should be a singleton, meaning no matter how many times it will be instantiated, it will always return the same object. This is important to avoid errors when working in large teams on the same website.
  2. The broker and all its actions should not depend on any external JavaScript library.
  3. The code should be as lean as possible and run quickly.

The Broker

The broker is the heart and soul of this solution and it look like this:

function pubsubBroker(){
	var instance = (function(){
		var subscribers=[];

		function isSubscribed(object, event){
			for(var i=0, l=subscribers.length; i<l; i++){
				if(subscribers[i].element === object && subscribers[i].action === event)
					return i;
			}
			return -1;
		}

		return {
			subscribe : function(object, event, callback){
				var exist = isSubscribed(object,event);
				if(exist!=-1)
					return;
				subscribers.push({element: object, action: event, callback: callback});
			},
			publish : function(event, args){
				for(var i=0, l=subscribers.length; i<l; i++){
					if(subscribers[i].action == event){
						subscribers[i].callback.call(this,args);
					}
				}
			},
			print : function(){
				for(var i=0, l=subscribers.length; i<l; i++){
					console.log(subscribers[i]);
				}
			}
		};
	})();

	pubsubBroker = function(){

		return instance;
	}

	return pubsubBroker();
}

Singleton

The “pubSubBroker” has an object named “instance” that holds its’ functionality. It has 3 methods: “subscribe” and “publish” which are used for the notification flow, and “print” for debugging.

When it is first created, the “instance” object is created. Than, the “pubSubBroker” is re-assigned to return the “instance” object, (line 35) and the function returns the new assigned “pubSubBroker” (line 40).

Subscription and Publishing

First, objects need to subscribe to future events. When they do so, the “pubSubBroker” checks if this object is already subscribed to this event,  to avoid duplications. Than this object is stored in a private array in the “pubSubBroker” object.

When an object fires an event, it need to notify the “pubSubBroker”, which in return check it’s subscriptions array and notifies the relevant objects.

That’s it, you can download the code and give it a try, and use it as you like.

Happy Coding :)

function pubsubBroker(){
var instance = (function(){
var subscribers=[];

function isSubscribed(object, event){
for(var i=0, l=subscribers.length; i<l; i++){
if(subscribers[i].element === object && subscribers[i].action === event)
return i;
}
return -1;
}

return {
subscribe : function(object, event, callback){
var exist = isSubscribed(object,event);
if(exist!=-1)
return;
subscribers.push({element: object, action: event, callback: callback});
},
publish : function(event, args){
for(var i=0, l=subscribers.length; i<l; i++){
if(subscribers[i].action == event){
subscribers[i].callback.call(this,args);
}
}
},
print : function(){
for(var i=0, l=subscribers.length; i<l; i++){
console.log(subscribers[i]);
}
}
};
})();

pubsubBroker = function(){

return instance;
}

return pubsubBroker();
}

Back to top