Understanding Event Emitters in NodeJS

The core idiom of NodeJS is Event Emitters. Most of the NodeJS Core Modules are built on top of the events module. In this tutorial, I will teach you what is Event Emitters and how we can make use of it in real-world scenarios.
What is Event Emitters?
You know that NodeJS is for javascript developers, but the other side of NodeJS is completely built in C++. The C++ side of NodeJS contains the libuv library which handles the events with the OS. Whenever an event completes in OS, libuv emits corresponding functions to happen. This concept is not available on the JavaScript side but NodeJS makes a fake Event Emitter concept which in turn become a popular module for most of the other NodeJS Core Modules like HTTP, FS, Streams etc.
Creating our own Event Emitters Concept:
To clearly understand what’s happening behind the scenes in NodeJS when using EventEmitters, we will build a simple EventEmitter class similar to NodeJS EventEmitters.
module.exports = class Emitter {
constructor() {
this.events = {};
}
on(type,listener) {
this.events[type] = this.events[type] || [];
this.events[type].push(listener);
}
emit(type) {
if(this.events[type]) {
this.events[type].forEach((listener) => {
listener();
});
}
}
}
I created a class named Emitter, Its constructor function creates an empty “events” object every time the Emitter class gets instantiated. The “on” method in the Emitter class is used to register the event with a listener function, the first line of the on method creates an empty event property if there’s no event with the same name in the “events” object. Otherwise, it assigns the older event property to it. Then, we push the listener function to the event property. The “emit” method in the Emitter class is used to emit the listener functions one by one corresponding to the event name passed inside the function as a parameter.
Using our Event Emitters:
var Emitter = require('./emitter');
var mobileEvents = new Emitter();
mobileEvents.on('call', () => {
console.log('Ringing');
});
mobileEvents.on('call', () => {
console.log("Vibrating");
});
console.log("make a call");
mobileEvents.emit('call');
To use our fake EventEmitters, we first require the module and then instantiate the Emitter class. As you know, The “on” method is used to register an event called “call” two times with two different listener functions. At the last line, The emit method is used to invoke all the listener functions. The output of the above code will be like this:
make a call
Ringing
Vibrating
Let’s make use of NodeJS Core EventEmitter:
To understand the concept of EventEmitters vividly, Let’s start thinking of a real-world example, your mobile is listening to a call event. When someone makes a call to your number, your mobile which is listening to the event will start (emit) to ring based on the settings you set up on your mobile.
const EventEmitter = require('events');
class mobileEvents extends EventEmitter {
constructor(ringtone,vibration) {
super();
this.ringtone = ringtone;
this.vibration = vibration;
}
ringing() {
console.log(`${this.ringtone} Ringing`)
}
}
const mobileEventEmitter = new mobileEvents('Titanic', true);
mobileEventEmitter.on('call', () => {
mobileEventEmitter.ringing();
});
function callToMyFriend() {
console.log('Connecting to your friend mobile');
mobileEventEmitter.emit('call');
}
callToMyFriend();
- Required the NodeJS events module.
- Created a class named mobileEvents extended from core EventEmitter.
- Inside the “mobileEvents” class, a constructor function is used in order to set up the ringtone and the vibration whenever an instance of this class gets instantiated.
- At last, a method named “ringing” is added in order to show the user that the mobile is ringing.
The Event Emitter Methods:
There are several useful methods available in NodeJS Core “events” module. I will explain the most often used ones here.
The “on” and “addListener” Method in Event Emitter:
The “on” and “addListener” methods in EventEmitter are event registration methods. It registers an event with a listener function. It takes two parameters, a name of the event and the listener function.
mobileEventEmitter.on('call', () => {
mobileEventEmitter.ringing();
});
mobileEventEmitter.on('call', () => {
console.log("second event listener");
});
mobileEventEmitter.on('call', () => {
console.log("third event listener");
});
An event can have more than one listener function. It’s better to limit the number of listener functions to below 10 per event (NodeJS restrict it too, to prevent the memory leaks).
The “emit” Method in Event Emitters:
While the “on” and “addListener” method is used to register an event, the “emit” method is used to emit the event, in other words, it invokes (calls) all the listener functions of the event.
mobileEventEmitter.emit("call");
When the compiler hits this line, it invokes all the listener functions of the event one by one in the order in which they are registered.
The “once” Method in Event Emitters:
The “once” method in EventEmitter is used to register a listener function, but in this case, once the event is emitted using the “emit” method, the listener functions which are registered using the once method will be removed from the events listener list.
mobileEventEmitter.once('call', () => {
console.log("once listener is emitted");
});
mobileEventEmitter.emit('call');
mobileEventEmitter.emit('call');
When you try to emit the “call” event for two times, you will get an output as follows:
//first time event emitted,
Titanic Ringing
second listener
third listener
once listener is emitted
//second time event emitted,
Titanic Ringing
second listener
third listener
The “removeListener” Method in Event Emitters:
There may be times when you have to remove a particular listener function in an event. The “removeListener” method accepts two parameters, the name of the event and the listener function which you want to remove.
const listenerFunction = () => {
console.log("I am listener funciton");
}
mobileEventEmitter.on('call', listenerFunction);
mobileEventEmitter.emit('call');
//output: I am listener function
mobileEventEmitter.removeListener('call', listenerFunction);
mobileEventEmitter.emit('call');
//output: false (when you print it in console)
The “removeAllListeners” Method in Event Emitters:
The “removeAllListeners” method wipe out all the listener functions from the event. It accepts an array of event names as a parameter. If you pass a single event name then the listener function corresponding to that event will be removed.
//removing single event listeners
mobileEventEmitter.removeAllListeners('call');
//removing multiples events listeners
mobileEventEmitter.removeAllListeners(['call','sms','data']);
Conclusion
There are so many other useful methods in NodeJS Event Emitters, I didn’t cover in this post, available in the NodeJS Events module. If you’re curious about it, take a look at NodeJS documentation on events module . If you have any other ideas or suggestions about NodeJS event emitters, please make a comment below. Thank You!