Node.js: Event Emitters and Listeners

When building client side applications with Javascript, events and handling them are quite common. Consider, for example,


$('#toBeClicked').on('click', function() { alert('clicked') })

Here we handle a click event on the element with id ‘toBeClicked’. When the element is clicked, a ‘click’ event is emitted which is handled by the above statement written by us.

Just like in the DOM,  many objects in node emit events. When they do so, they inherit from the EventEmitter constructor.

Lets straight away build a custom event emitter and see whats going on,


EventEmitter = require('events').EventEmitter       // The Event Emitter constructor in the events.js module .

Now, we create our custom emitter which is an instance of EventEmitter,

emitter = new EventEmitter();

We listen for the error event,

emitter.on('error', function(msg1, msg2) { console.log('ERR: ' + msg1 + ' ' + msg2 ) })

Here, function(msg1, msg2) { console.log('ERR' + msg1 + ' ' + msg2 ) }

is the callback to be performed once the event is emitted,

We could also listen as,

emitter.addListener('error', function(msg1, msg2) { console.log('ERR: ' + msg1 + ' ' + msg2 ) } )

Now we emit the error event,

emitter.emit('error', 'Bug detected', '@ Step 4')

Once the ‘error’ event is emitted, the listener performs the callback and we see the error logged in the console(as we have written in the callback function)
ERR: Bug detected @ Step 4

We could add listeners on any more custom events and handle them when the event is emitted.

Now that we have got to know how events are emitted and handled via listeners, lets try out a small server that listens for requests and processes them.


var http = require('http'),
    sys = require('sys');

var server = http.createServer(function(request, response) {
  request.on('data', function (chunk) { console.log(chunk.toString()); });

  request.on('end', function() {
    response.write('Request Completed!');
    response.end();
  });

});

console.log("Starting up the server");
server.listen(8000);

Here, http.createServer method returns an object which inherits from the EventEmitter constructor.

Check out the nodejs api doc for the createServer method in the http.js module,

http.createServer([requestListener]), It says that requestListener is a function which is automatically added to the ‘request’ event.

To check whats going on behind the scenes here, lets dive into the code base of nodejs,
As can be seen from code, the createServer method is within the http.js module. Inspecting the http.js module,

exports.createServer = function(requestListener) {
  return new Server(requestListener);
};

Check for the _http_server.js module to find the Server constructor which has the following lines of code,

if (requestListener) {
  this.addListener('request', requestListener); // event listener for the server
}

As per the above snippet, ‘this‘(the current server instance ) listens for the ‘request’ event and attaches the requestListener function to be performed when the event is emitted.

Here,

function(request, response) {
  request.on('data', function (chunk) { console.log(chunk.toString()); });

  request.on('end', function() {
    response.write('Request Completed!');
    response.end();
  });
}

is our requestListener.

Now, further inspecting the _http_server.js modulewe could also see how the request event is emitted,

self.emit('request', req, res); // event emitter for the server

‘req’ and ‘res’ are the request, response objects that are passed as arguments to the requestListener function called when the ‘request’ event is emitted. Here self is ‘this’ ( our current server instance).

We could well make the server listen for the request event on our own. For this,

var server = http.createServer()
server.on('request', function(request, response) {
  request.on('data', function (chunk) { console.log(chunk.toString()); });

  request.on('end', function() {
    response.write('Request Completed!');
    response.end();
  })
});

Here when we create the server instance, we do not pass the requestListener( Do notice that requestListener was only optional in http.createServer([requestListener]) ). Instead we attach a listener of our own on the server which listens to the ‘request’ event and performs the callback function when the request event is emitted, i.e,

server.on('request', function(request, response) { ... });
Advertisements

One response to this post.

  1. whoah this weblog is great i really like reading your articles. Stay up the great work! You recognize, a lot of persons are hunting around for this information, you could aid them greatly. |

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s