---
title: Custom event emitters in Javascript
teaser: 'Learn how to create a real time activity dashboard using event emitters in
  Javascript.

  '
tags: javascript,websockets,new bamboo,web
author: Ismael Celis
published_on: 2010-07-14
---

_This post was originally published on the New Bamboo blog, before [New Bamboo
joined thoughtbot in London][new-bamboo-thoughtbot]._

---

<iframe width="500" height="313" src="//player.vimeo.com/video/13181356" frameborder="0"></iframe>

<small>Websockets-based activity dashboard app. Read on to know more about the
ideas behind it</small>

In this post I'll attempt to summarise some patterns for designing event-based
Javascript applications extracted from our projects and previous blog posts on
the subject. I'll end with an overview of the techniques described and how they
play together in a real-world application. This post is a follow-up from a
presentation at the [London Javascript User Group].

## Background

We've blogged about [Javascript patterns for complex applications] before. If
you're short on time, that post describes the way we lay out our client-side
apps here at New Bamboo. It's an MVC-like setup where we have Model objects
doing the persistence and data binding, and View objects listening to state
change in those models via the observer patterns and custom events. If you
haven't, I strongly recommend you read that post before this one.

The key component of this approach is using custom events to decouple the
communication between layers. This is a simple View example <sup>\*</sup>:

<div class="highlight" style="background: #C8E282; padding: 1em; margin: 1em 0;">
  <sup>\*</sup> The examples in this page <strong>will use jQuery's event
  triggering and DOM functions</strong> for simplicity.
</div>

```javascript
var UserPane = function(event_source, $container){

  function update(event, user){
    $container.append('<li>'+user.name+'</li>')
  }

  $(event_source).bind('user_added', update)
}
```

And you would use it like:

```javascript
new UserPane(document, $('ul#user_list'));

// Wrap DOM events and re-trigger with useful data using jQuery
$('#users input:radio').change(function(evt){
  $(document).trigger('user_added', {name: $(this).val()});
});
```

The example defines a View class that knows in which DOM element to render
content ($container) and binds itself to the 'user_added' event triggered on the
document object by other layers in the application.

We're passing the <code>document</code> element as the source of events, but
you're free to swap it by anything that you can bind to and trigger events from.
It doesn't even need to be a DOM element, and this is where OO and evented
programming starts to look less counter-intuitive than one might have thought:
you can build your own Event Emitters and model your domain around them.

## Event Emitters In the wild

That is exactly what libraries such as Node.js are doing with an [EventEmitter]
class you can extend from. The following is an object that emits a "tick" event
with a random number every 5 seconds.

```javascript
var EventEmitter = require('events').EventEmitter,
    puts = require('sys').puts;

var Ticker = function( interval ){
  var self = this,
      nextTick = function(){
    self.emit('tick', Math.random() * 1000);
    setTimeout(nextTick, interval);
  }

  nextTick();
};

// Extend from EventEmitter 'addListener' and 'emit' methods
Ticker.prototype = new EventEmitter;

// A ticker instance with an interval of 5 seconds
var ticktock = new Ticker( 5000 );

// Bind an event handler to the 'tick' event
ticktock.addListener('tick', function( number ) {
  puts('number emitted: '+ number);
});
```

The nice thing about this is that objects interacting with the Ticker instance
only need to bind themselves to events emitted by it. There's no need for public
methods apart from `addListener` (or `$.bind` in our previous jQuery example).

## How we use Event Emitters

Back in the browser side of things, you can build event emitters that represent
objects in your domain and trigger events when their status changes. Then other
parts of the application can observe those events and react accordingly. A nice
abstraction of this pattern is [js-model], an ORM-like Javascript library we
developed to model domain objects with extra server persistence baked-in.

```javascript
// Js-model example
var Post = Model("post")

Post.bind("add", function(new_post) {
  addObjectIntoUI(new_post)
})

// This will trigger the 'add' event on the Post object,
// executing any handlers observing it.
var post = new Post({ foo: "bar" })
```

More info on js-model on [its documentation page][js-model-docs].

This is also the approach that we've taken with our [Pusher] websockets service.
With it you can bind your local objects to events coming from the server in a
completely transparent way.

```javascript
var server = new Pusher('you app key', 'some channel');

server.bind('user_added', function(user){
  $('ul#user_list').append('<li>'+user.name+'</li>')
})
```

And of course you would build your own objects to do the binding and keep your
main app clean and expressive.

```javascript
new UserPane( server, $('ul#user_list') );
```

I talk about how this is done in this post about [json websockets].

## Do it yourself

Because Pusher.js is framework-agnostic, we don't use jQuery's event-binding
API. Instead, Pusher implements its own <code>bind</code> method. But once
you're using this pattern in one part of your app there's no reason you couldn't
use it for the rest of your domain objects. The only thing they need to do is
implement binding and triggering of events. Here is a [simple abstract
prototype] you can use in your own objects. This is the Ticker example again
using that snippet:

```javascript
/* Periodically send out dummy events
--------------------------------------------*/
var Ticker = function( interval ){
  var self = this,
      nextTick = function(){
    self.trigger('tick', Math.random() * 1000);
    setTimeout(nextTick, interval);
  }

  nextTick();
};

// Extend from AbstractEventsDispatcher 'bind' and 'trigger' methods
Ticker.prototype = new AbstractEventsDispatcher;

var ticktock = new Ticker( 5000 );

ticktock.bind('tick', function( number ) {
  puts('number emitted: '+ number);
});
```

The only reason I've changed 'addListener' to 'bind' and 'emit' to 'trigger' is
to keep it familiar for jQuery users.

What's important here is that once you model your objects around this minimal
event-centric interface ('bind' and 'trigger') it makes little difference what
your event emitter objects actually do -and how they do it. You app can be fully
evented while retaining the best bits of object orientation such as polymorphism
and inheritance.

## A working application

I've recently built an activity dashboard app that uses Pusher when deployed to
production but a mocked, in-browser event emitter object in development to
simulate a stream of events coming from the server. My View objects are
oblivious to the origin of those events and just focus on binding to them and
rendering them onscreen as they come. You can see it working on the video above.

It starts by defining a series of self-contained widget objects. I then loop
through them and instantiate each with the same instance of an event emitter -in
this case Pusher or a mock server implementing <code>bind</code> for custom
events.

This is the basic code:

```javascript
var server = new MockServer() // or new Pusher('app_key', 'channel_name'), or your own event emitter

// Instantiate widgets
for(widget in Widgets.available){
  new widget( server );
}
```

And this is a simplified widget that listens to 'closed_order' events and plays
a sound using HTML5's audio tag:

```javascript
Widgets.available.soundAlert = function( server ){

  // add audio files to document
  var $audio = $('<audio src="/audio/alert.mp3" preload="true" />').appendTo('body');

  function play(data){
    $audio.load().play();
  }

  // bind to events you want to alert
  server.bind( 'order_closed', play )
}
```

I can add as many widgets as I want (and even remove them, pause them and
inspect them in run-time), with no dependencies between them. Because they bind
themselves to events they're interested in, each one is completely [orthogonal]
to the system.

Finally, this is an example of the MockServer object I use to replace Pusher for
development purposes:

```javascript
/* Periodically send out dummy events
--------------------------------------------*/
var MockServer = function(){

  var self = this, interval, event_names = ['order_closed', 'order_cancelled', 'order_shipped'];

  function randomEvent(){
    var event_name = event_names[Math.round(Math.random()*2)];

    self.trigger(event_name, {
      info: 'Mock order, 3 products',
      total: Math.random() * 1000
    });
  }

  interval = setInterval(randomEvent, 2000);
};
// Extend event-binding interface
MockServer.prototype = new AbstractEventsDispatcher;
```

## Wrap up

This illustrates the general architecture that permeates all recent Javascript
projects that we've developed. In future articles we'll talk about techniques
and specific problems in more detail.

Even though I've included an abstract class that I used for the examples on this
page, the emphasis is on the patterns more than on particular implementations
and APIs.

[EventEmitter]: http://nodejs.org/api.html#eventemitter-14
[Javascript patterns for complex applications]: https://thoughtbot.com/blog/why-your-javascript-apps-need-more-structure
[js-model-docs]: http://benpickles.github.com/js-model/
[js-model]: https://thoughtbot.com/blog/the-js-model-layer
[json websockets]: https://thoughtbot.com/blog/json-event-based-convention-websockets
[London Javascript User Group]: http://www.meetup.com/javascript-3/calendar/13838645/
[new-bamboo-thoughtbot]: https://thoughtbot.com/blog/new-bamboo-joins-thoughtbot-in-london
[orthogonal]: http://en.wikipedia.org/wiki/Orthogonality#Computer_science
[Pusher]: http://pusherapp.com
[simple abstract prototype]: http://gist.github.com/464257
