Node.js Events and EventEmitter

SitePoint Sponsors
SitePoint Sponsors
Share

One of the reasons for Node.js’ high speed is the fact that it is coded around events. Instead of reading all the files necessary with every request (like PHP), with Node you just start your server, initiate most of the variables, declare your functions and then just wait for an event to occur. While Node.js has some useful built-in events, like the request event, wouldn’t it be useful to be able to create our own events and be able to trigger them ourselves? That’s what I’m going to talk about in this article. First I will show you how normal events are emitted. As event I will take the example that when a person enters a shop, a bell may ring to show his presence.  It will act a bit like the observer pattern where our event acts like subject and all functions attached to the event are like observers. So the shop example:

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

var ringBell = function ringBell()
{
  console.log('ring ring ring');
}
eventEmitter.on('doorOpen', ringBell);

eventEmitter.emit('doorOpen');
First we load the events module, which is part of the Node.js core. Then we create a new instance of the EventEmitter class (which we are going to extend later). After then we place the ringBell function inside a variable so that it can be called that way. It simply prints ‘ring ring ring’ in our console. Now the interesting things are coming. We add our ringBell
function to the function list of the doorOpen event. This is done by the eventEmitter.on() method and as first argument the event, as second argument the function to be added. This doesn’t really do anything, it just registers our function. The real magic happens the line after that, when we emit our event. Calling the emit() method will execute all the functions that are registered with the on method. This isn’t that interesting, could just have called that one function if we wanted the bell to ring. But that’s what makes events that interesting: you can register just as many functions as you want. We could also have done this, for example:
eventEmitter.on('doorOpen', ringBell);
eventEmitter.on(‘doorOpen’, doSomething);
eventEmitter.on(‘doorOpen’, doSomethingElse);

eventEmitter.emit('doorOpen');
That would also work and would more use the functionalities that the EventEmitter provides us. We can also use functions with arguments as listeners:
eventEmitter.on(‘doorOpen’, function(ring)
{
    Console.log(ring);
}
eventEmitter.emit(‘doorOpen’, ‘ringeling’);
We just pass the arguments in the emit() method. While this is all very powerful, a common practice within the Node community is to inherit from the eventEmitter class. We could do this by having a door class, with an open() method which will emit the doorOpen event. Take a look at this code:
var events = require('events');

function Door(colour) {
  this.colour = colour;
  events.EventEmitter.call(this);

  this.open = function()
  {
  this.emit('open');
  }
}

Door.prototype.__proto__ = events.EventEmitter.prototype;

var frontDoor = new Door('brown');

frontDoor.on('open', function() {
    console.log('ring ring ring');
  });
frontDoor.open();
In the constructor of our Door object, we set the colour of the door and, we use the call() method of our EventEmitter object, which executes the constructor method of EventEmitter. Then we declare our open method, which emits the ‘open’ event. This line:
Door.prototype.__proto__ = events.EventEmitter.prototype;
Copies all of the EventEmitter properties to the Door object. Then we create our front door, which is an instance of Door and which has a brown-ish colour. We then add an event listener and finally we open the door, and print a message to our console. I hope you all see that this events module is very powerful and useful! Then finally, the events module provides us with a way to list all of the event listeners, attached to an event and a way to delete event listeners.
var ring = function()
{
    console.log('ring');
}
frontDoor.on('open', ring);

console.log(require('util').inspect(frontDoor.listeners('open'))); // Outputs ring
You can do that by using the listeners
property. Of course this only works if you didn’t use an anonymous function as event listener. If we would ever want to, we could remove the bell from our door:
frontDoor.removeListener('open', ring);
Or we could even remove all the listeners:
frontDoor. .removeAllListeners(‘open’);
Thank you for reading this guide, I hope that you’ve learned something. See you next time!

Frequently Asked Questions (FAQs) about Node.js Events and EventEmitter

What is the EventEmitter class in Node.js and how does it work?

The EventEmitter class is a core module in Node.js that facilitates communication between objects. It is part of the ‘events’ module and is used to emit and handle custom events. The EventEmitter class works by registering functions or event handlers to named events. When the EventEmitter object emits an event, all the functions attached to that event are called synchronously.

How do I create an instance of EventEmitter?

Creating an instance of EventEmitter is straightforward. First, you need to import the ‘events’ module. Then, you can create a new instance using the ‘new’ keyword. Here’s a simple example:
const EventEmitter = require('events');
const myEmitter = new EventEmitter();

How can I emit events using EventEmitter?

To emit events, you can use the ’emit’ method of the EventEmitter instance. This method allows you to specify the event name and pass any number of arguments to the event listeners. Here’s an example:
myEmitter.emit('event', 'arg1', 'arg2');

How can I listen to events using EventEmitter?

To listen to events, you can use the ‘on’ method of the EventEmitter instance. This method allows you to specify the event name and a callback function that will be invoked when the event is emitted. Here’s an example:
myEmitter.on('event', function(arg1, arg2) {
console.log(`event with args ${arg1}, ${arg2} occurred`);
});

What is the difference between ‘on’ and ‘once’ methods in EventEmitter?

The ‘on’ method allows you to add a callback function that will be invoked every time the event is emitted. On the other hand, the ‘once’ method allows you to add a callback function that will be invoked only the first time the event is emitted.

How can I remove an event listener from EventEmitter?

To remove an event listener, you can use the ‘removeListener’ or ‘off’ method of the EventEmitter instance. This method allows you to specify the event name and the callback function that should be removed. Here’s an example:
myEmitter.removeListener('event', callback);

Can I limit the number of listeners for an event in EventEmitter?

Yes, you can limit the number of listeners for an event using the ‘setMaxListeners’ method of the EventEmitter instance. This method allows you to specify the maximum number of listeners that can be added for an event.

How can I get the number of listeners for an event in EventEmitter?

To get the number of listeners for an event, you can use the ‘listenerCount’ method of the EventEmitter instance. This method allows you to specify the event name and returns the number of listeners for that event.

Can I emit and handle errors in EventEmitter?

Yes, you can emit and handle errors in EventEmitter. If an EventEmitter does not have at least one listener registered for the ‘error’ event, and an ‘error’ event is emitted, the error is thrown, a stack trace is printed, and the Node.js process exits.

Can I use EventEmitter in the browser?

While EventEmitter is a Node.js module and is primarily used in server-side applications, there are browser versions available. These can be used in the same way as the Node.js version, allowing you to use the same event-driven architecture in your client-side code.