Communication between objects in JavaScript applications

Some time ago, while I was working on a project I again came across a problem that resurfaces from time to time on different projects. Problem in question is object to object communication in JavaScript.

At first glance this does not seems to be something difficult to handle, on the contrary it looks to be quite straight forward. What would be simpler than to call other object's method from inside other object? All you need know is what object and what method to call. Then just place it inside desired object's method and everything is working.

As simple as it looks, above approach is sufficient only in simplest of cases. Things get more complicated when you have to interact with several objects, although this is still not that difficult to handle. But imagine a situation when you don't know how many objects you need to access, of what type (class) they are and which method you have to call. As strange and unlikely as it may seems, such situation can occur and it is not that rare.

Best example of it is a user generated list of items. Lets say that user can create several items on a list, in our case a list of vehicles. There are different types of vehicles available (like plane, car, boat) and each of them, when added, is represented by different type of object. These objects can share some of the features and methods, but undoubtly also have some unique parts in them. At the time you are writing code, you cannot tell what type of vehicles will be on the list nor how many of them there will be. With this particular example programmer can crate some code that will keep track of this items and give access to different types of vehicles or all of then when desired.

The Solution

But as I mentioned before this problem keeps resurfacing from time to time on different projects in different form. Being tired of fighting the same fire each time I tried to create a generic solution to this problem. Looking through internet for an inspiration I have encountered a solution that is already in place in several programming languages, operating systems etc.

The solution I am talking about are SIGNALS. To describe it in simple way, it is a way of sending messages to different recipients (applications, objects etc) without actually pointing out where it should go to. On other side of the process, potential recipients are 'listening', and when they 'hear' signal they recognize they are acting accordingly to it. It is like shouting to a crowd 'Who knows how to swim, go to the pool', and people who can, will go there, but while you are shouting your command, you don't really know who, if anyone, will respond.

Of course this explanation is really simple and not complete, and programmers familiar with it may laugh at it, but for our needs it is enough to start with.

Based on what I've read I decided that what I need is a JavaScript object that will handle all inter-object communication in JS. This object will receive and relay all signals.

Before I started coding it, I've set few goals this object has to achieve:

  • unified access for all objects
  • be able to pass custom data along with signal

The Code

Below is a sample code I have created for signaling in JS:

Sample code for signalling in JavaScript
var SignalBus = {

  signals: {},

  listen: function ( signal, fn ) {
    if( !this.signals[signal] ) {
      this.signals[signal] = new Array();
    }
    this.signals[signal].push( fn );
  },

  dispatch: function ( signal, params ) {
    if( this.signals[signal] ) {
      var sigList = this.signals[signal]
      for( var i = 0; i<sigList.length; i++ ) {
        this.sigList[i]( params );
      }
    }
  },

  remove: function ( signal, fn ) {
    if( !this.signals[signal] ) {
      var tmp = new Array();
      var sigList = this.signals[signal]
      for( var i = 0; i<sigList.length; i++ ) {
        if( this.sigList[i] != fn ) {
          tmp.push( this.sigList[i] );
        }
      }
      this.signals[signal] = tmp;
    }
  }

}

Above class has 4 members:

signals an object that holds all defined signals along with pointers to functions that listens to it, it is a main 'storage' area for our object and only variable

listen a method that is invoked when new function ( param: fn ) is going to listen for a signal ( param: signal ).

dispatch a method used to actually call a signal with any arguments passed to it. Arguments has to be in a form of an array. Any function associated with it will be called with passed arguments.

remove oposite to listen, remove function from listeners list.

The example of using this class is below:

Example use of class
var Object1 = {

  start: function () {
    SignalBus.listen( 'SIGNAL_DO_SOMETHING', function ( args ) { Object1.doSomething.apply( Object1, args ); } );
  },

  doSomething: function ( a, b ) {
    alert( a + ' has done something to ' + b );
  }

}

var Object2 = {

  start: function () {
    SignalBus.dispatch( 'SIGNAL_DO_SOMETHING', [ 'John', 'Jane' ] );
  }

}

Object1.start();
Object2.start();

In this example, Object1 listens for a signal and Object2 dispatches it.

The Conclusion

It may look a bit odd to create all this code just to call a method from one object from within an another one.

To appreciate it, think of a situation when you need to add another object that will react to the same signal, but you don't want to change anything in existing code. Without signals, you couldn't do it, as you would have to modify Object2.start() to accommodate for another object. With signals implemented, all you have to worry about is to remember while coding new obhject to make it listen to proper signals, older code does not have to be updated.

Also, if presence of object that will listen to a signal is not hardcoded, in other word it depends on user's actions there is no need to add any detection code in dispatching object, if this object does not listen, or does not even exist, nothing will happen.

Signals is a simple and flexible solution, which programmers will aprreciate more and more as their applications grow in size. Above code is just an example, it can be improved in many ways, but even in this basic and simple form it can be really useful.

Useful links

Comments

There are no comments for this post

Leave a comment

Antispam code

Enter the text you see to the left

Web Design Shrewsbury telephone 08000 805401

Web Design Manchester telephone 0161 7440075

Web Design Birmingham telephone 0121 7750085

Web Design London telephone 0207 1250044

Valid XHTML/CSS © Mutiny Design - Website Design and Development - Network House, Badgers Way, Oxon Business Park, Shrewsbury, Shropshire SY3 5AB