Community Post

Node.js: Event Emitter

Eric Uldall

Node.js is becoming more popular every day and chances are if you've written code in node before you've been influenced by the Event Emitter.

What is it?

The Event Emitter in node is exactly what it sounds like, a super class that emits events... Well, cool! What does that even mean?

In node we go beyond the stereotypical approaches to normal everyday problems that occur in async, which are normally solved using callbacks. As we all know callbacks can lead to a gigantic funnel in your code that becomes more or less difficult to manage and isn't pretty to look at.

With the use of the Event Emitter we can now take all those callbacks and transition them to an event driven structure.

Sample:

var bad_fs = require('not_a_real_fs_module');
var rs = bad_fs.createReadStream('datasource', function(chunk){
   if( chunk ){
      rs.next(function(chunk){
          if( chunk ){
             rs.next() //etc...
          }
      });
   }
});

In some scenarios this works (it does not fundamentally work for the above example), though, as you can see, it doesn't really scale. What about a scenario where you want to do something every time a chunk of data is read? This is where you will find Event Emitters very useful and they are used in the real fs module.

Sample:

var fs = require('fs');
var data = '';
fs.createReadStream('datasource').on('data', function(chunk){
    //each time a chunk of data is read, this function will execute
    data += chunk;
}).on('end', function(){
    //no more chunks
    console.log(data); //the full body of data read
});

Externally this pattern makes a lot of sense and you've probably seen it before. The great thing is there is no limit to the number and type of events you might include in your module and adding new events is quick, easy and doesn't require breaking changes. Here's where you can learn how to implement this super class in your own node modules.

How to implement Event Emitter

Fortunately the events module is available by default in node, so there's no need to npm install anything for this.

Step 1: Create a constructor for your object

var myObject = function(){};

Step 2: Inherit the Event Emitter

var EventEmitter = require('events').EventEmitter; //this is included in node
var util = require('util'); //this is included in node as well

var myObject = function(){
    EventEmitter.call(this);
};

util.inherits(myObject, EventEmitter);

Step 3: Add some methods to your prototype

myObject.prototype.doSomething = function(thing){
    this.emit('something', thing);

    return this; //make your method chainable, for ease of use
};

Step 4: Use it!

var obj = new myObject;
      obj.on('something', function(thing){
          console.log(thing);
      });

     obj.doSomething('eat').doSomething('sleep').doSomething('code');

RUN IT ON TONIC: https://tonicdev.com/thelettereproduction/event-emitter

CHECK OUT THE EVENT EMITTER DOCS: https://nodejs.org/api/events.html

Conclusion

The Event Emitter is at the core of node.js programming and is even the super class of the node process object. Sometimes it's a great way to replace callbacks and promises and other times it's just a supliment to them. Whatever the case, there's no doubt knowing how to use the Event Emitter will take your game to the next level. Enjoy!

Eric Uldall

1 post

Solving problems using different methods of problem solving. If it works...Ship It! If it can work better... yea lets do that too.