Events and Emitters

in Node JS

Much of Node.js core API is built around an asynchronous and eventdriven architecture.

Events and Node.js

Objects called emitters, trigger named events, that cause listener functions to be called.

This is very similar to Events in the browser!

var EventEmitter = require('events').EventEmitter;

The EventEmitter class

The EventEmitter class is imported from the Node.js events module.

Note: the EventEmitter class is exported by default when you require the events module. So you can also do:

var EventEmitter = require('events');

Extending EventEmitter

Typically, most classes extend EventEmitter.

var EventEmitter = require('events').EventEmitter;
var util = require('util');

function MyEmitter() {
  EventEmitter.call(this);
}
util.inherits(MyEmitter, EventEmitter);

Note: You can use class declarations and extends in Node v6.

You can accomplish this by using the util.inherits method.

Event handlers, or listeners, are callbacks that may be attached to an instance of an EventEmitter.

  • Listeners are invoked when an event is emitted by that object.
     
  • If multiple listeners are added to an EventEmitter they are executed sequentially in the order they were added.
     
  • When the event handler is invoked,  the context of the callback is the instance of the EventEmitter.

Event Handlers

Adding listeners

Listeners may be added to events using either the on or addListenerEvent method.

var emitter = new MyEmitter();

emitter.on('event', function () {
  console.log('An event happened!');
});

emitter.addListener('event', function () {
  console.log('It really did!');
});

Note: addListenerEvent is just an alias for on.

Emitting an Event

emitter.on('event', function () {
  console.log('An event happened!');
});

emitter.emit('event');  // 'An event happened!'

Listeners are called when the event emitter emits the named event.

Removing a listener

var callback = function () {
  console.log('An event happened!');
};

emitter.on('event', callback);
emitter.emit('event');  // 'An event happened!'

emitter.removeListener('event', callback);

The removeListener method will remove, at most, one listener from the listener array.

Removing all listeners

var callback = function () {
  console.log('An event happened!');
};

emitter.on('event', callback);
emitter.on('event', callback);
emitter.on('event', callback);

emitter.emit('event');  // 'An event happened!' x 3

emitter.removeAllListeners('event');

You can also use removeAllListeners to remove every listener assigned to an EventEmitter.

Creating an

Event Emitter

Define a class

function Timer () {

  setInterval(function () {
    // do something every 1000ms
  }, 1000);
}

Extend EventEmitter

var EventEmitter = require('events');

function Timer () {
  EventEmitter.call(this);

  setInterval(function () {
    // do something every 1000ms
  }, 1000);
}

Timer.prototype = new Object(EventEmitter.prototype, {
  constructor: {
    value: EventEmitter,
    configurable: true,
    enumerable: true,
    writable: true
  }
});

the old way

Using Node util

var EventEmitter = require('events');
var util = require('util');

function Timer () {
  EventEmitter.call(this);
  
  setInterval(function () {
    // do something every 1000ms
  }, 1000);
}

util.inherits(Timer, EventEmitter);

for easier inheritence

Create a new instance

var myTimer = new Timer();

myTimer.on('tick', function(){
  process.stdout.write('tick \n');
});

and add an event listener

Emit the event

function Timer () {
  EventEmitter.call(this);

  var self = this;

  setInterval(function () {
    self.emit('tick');
  }, 1000);
}

named 'tick'

Send data back

function Timer () {
  EventEmitter.call(this);

  var self = this;
  var i = 0;

  setInterval(function () {
    self.emit('tick', { interval : i++ });
  }, 1000);
}

to the event handler

like callback arguments

use event argument

myTimer.addListener('tick', function(event){
  process.stdout.write('tick ' + event.interval + '\n');
});

name the event handler

function tickHandler(event){
  process.stdout.write('tick ' + event.interval + '\n');
}
myTimer.addListener('tick', tickHandler);

remove the

event handler

function tickHandler(event){
  process.stdout.write('tick ' + event.interval + '\n');
  if(event.interval == 5){
    myTimer.removeListener('tick', tickHandler);
  }
}
myTimer.addListener('tick', tickHandler);

Using this context

function tickHandler(event){
  process.stdout.write('tick ' + this.i + '\n');
  if(this.i == 5){
    this.removeListener('tick', tickHandler);
  }
}
myTimer.addListener('tick', tickHandler);
function Timer () {
  EventEmitter.call(this);
  var self = this;
  this.i = 0;
  setInterval(function () {
    self.emit('tick', { interval : self.i++ });
  }, 1000);
}

Remember this!

Look for objects or classes that extend EventEmitter
it means you can listen for events that it will emit.

Check the class api documentation or source code
for what events it will emit, and the contents of the event object it passes back to the handler.

emitter.on('data', function(event){...});

What are you ? -----v

^----- What other events do you emit?

Resources

Copy of Events and Emitters in NodeJS

By Tony Gaskell

Copy of Events and Emitters in NodeJS

  • 1,589