Event Emitter

by Toby Ho on 2/17/2014

Module Summary

Node.js:
events
Component:
component/emitter
Bower:
eventEmitter
Dependencies:
None
LOC:
302/112/308
File size minified:

4.2k/1.3k/2.8k

Today I am going to cover the event emitter. What is an event emitter? Well, it's a simple library for attaching events to JavaScript objects.

A Little History

Event emitter first appeared as a core library in Node where it has proven to be a useful pattern. Since the library itself is not specific to Node at all, it has found uses in the browser as well. There are now many implementations of event emitter - partly due to how easy it is to implement its API. Here, I am going to cover the event emitter API that is common to most implementations.

Registering

Let's say there is job object which happens to be an event emitter. To register an event handler for the event done, you'd use the on method like so:

job.on('done', function(){
  console.log('The job is done!');
});

Emitting

Now if you are writing the code responsible for actually performing the job, you'll need to notify all the handlers that the job was done at the end. How do you do that?

job.emit('done');

You can also pass arguments to the event, for example the time when the job was done.

var timeDone = new Date();
job.emit('done', timeDone);

The arguments will passed in the same order to all the handlers.

job.on('done', function(timeDone){
  console.log('Job was pronounced done at', timeDone);
});

Removing Handlers

To remove an active event handler from an event emitter, you'd use the removeListener method

function onDone(timeDone){
  console.log('Job was pronounced done at', timeDone);
}
job.on('done', onDone);
...
job.removeListener('done', onDone);

Or you could use the removeAllListeners method to remove all handlers associated with an event:

job.removeAllListeners();

Fire Just Once

The event emitter API also has a convinient shorthand for registering a handler to be called once, and once only, it's called once().

job.once('done', function(){
  // This callback will only be called the
  // first time `done` is fired.
});

Make Your Own Event Emitter

So, that's great, but how do you make an event emitter of your own? You inherit EventEmitter.

function Job(){
  EventEmitter.call(this);
  // custom initialization here
}
Job.prototype = new EventEmitter;

I find that this is the simplest way to inherit EventEmitter without using any utilities. To make it even simpler, the line EventEmitter.call(this) is not strictly necessary since EventEmitter`s constructor doesn't do anything - but people have been told to add this in just in case it ever does in the future.

There are other flavors of inheriting EventEmitter. I will list them here in case you encounter them and get confused. So, in place of Job.prototype = new EventEmitter, you could also:

  1. Use an inheritance function like Node's util.inherits or component/inherit:
     inherit(Job, EventEmitter)
    
  2. Use __proto__ but this is is not supported in IE 10 and older (I am partial to this one if I am doing Node-only stuff):
     Job.prototype.__proto__ = EventEmitter.prototype
    
  3. Mixin instead of inherit, i.e. copy over the methods, with an extend function like xtend or _.extend or just write your own:
     extend(Job.prototype, EventEmitter.prototype)
    
  4. Built-in mixin capability as implemented by component/inherit
     EventEmitter(Job.prototype)
    

Regardless of which of the above you use, you can create a job with the new operator

var job = new Job

and it is indeed an event emitter!

Where To Get It?

Some implementations have more extra features, but they will all support the basic features covered above.

comments powered by Disqus