Nodejs Event Loop and Event Emitter

We offer you a brighter future with FREE online courses - Start Now!!

In this article, we will be discussing what is event loop in Nodejs, what are the different phases, what is event emitter, how it works and what are the different methods present in it.

Difference between Nodejs Events and callback:

In callback, the function executes after the asynchronous function has returned its result whereas a function in event executes as soon as the corresponding event has been fired.

Event Loop in Nodejs:

Node js uses javascript and we know that javascript is single threaded and synchronous than how node js maintains concurrency? In order to achieve it, nodejs has events and callbacks. Event loop is an infinite loop and in each iteration it checks the event queue for any triggered event, if found it then executes it and removes it from the queue.

Phases in Event Loop:

1. Timers:

In this phase, execution of callbacks scheduled by setTimeout() and setInterval() takes place.

The callbacks made by setTimeout() and setInterval() are known as timer callbacks, and these callbacks will try to execute as soon as the specified time has passed.

2. Pending Callbacks:

In this phase, execution of callbacks that were deferred takes place.

3. Poll:

It retrieves new I/O events and executes I/O callbacks

4. Check:

Callbacks from setImmediate() are invoked here.

5. Close callbacks:

Some of the close callbacks are socket.on(‘close’) etc

Nodejs setImmediate() vs setTimeout()

Technology is evolving rapidly!
Stay updated with DataFlair on WhatsApp!!

setImmediate(): It executes once the current poll phase is over

setTimeout(): It executes after a threshold amount of time has passed.

The order of execution of the above timer depends where we are using them, if both are written in the main module then it can be impacted by other applications.

Example of setimmediate and setTimeout in Nodejs:

When you run the below code you will observe that sometimes setTimeout() executes first and sometimes setImmediate() executes first.

Code for comparing setimmediate and setTimeout:

setTimeout(() => {
    console.log('setTimeout executed');
}, 0);
 
setImmediate(() => {
    console.log('setImmediate executed');
});

Output:

nodejs-setimmediate and set timeout in main

When we will be using these timers inside an I/O cycle then always the setImmediate will execute first.

Code for setimmediate and setTimeout inside filesystem

const fs = require('fs');
 
fs.readFile("DataFlair.txt", () => {
    setTimeout(() => {
        console.log('timeout');
    }, 0);
    setImmediate(() => {
        console.log('immediate');
    });
});

Output:

nodejs settimout and set immedaite inside IO

process.nextTick():

It is a part of asynchronous api. Whenever we pass callbacks to process.nextTick() what happens is that all these callbacks are resolved before the continuation of the event loop. Due to this, starvation may occur.

Why to use process.nextTick()?

It allows users to easily handle errors, cleanups and also if we want to run a callback after the call stack was unwound.

process.nextTick() vs setImmediate() in Nodejs:

The callbacks in process.nextTick() are called immediately whereas in setImmediate() callbacks execute in the next iterations of the event loop.

Nodejs Event Emitter and its working

Event Emitter is a class that is capable of emitting an event, attaching an event and also detaching it. Https and other node js core modules use the event emitter class.

Event emitter class calls all the events in the same order in which they were registered.

The on() method is used to attach the event handler, this method takes a callback function which gets attached to the event. More than one function can also be attached to a single event.

The emit() method is used to emit the attached event, basically it invokes the attached function.

Code for event emitter:

const EventEmitter = require('events');
const emitter = new EventEmitter();
 
function event1() {
    console.log('First event occurred!')
}
 
function event2() {
    console.log('First event occurred!')
}
 
emitter.on('someevent', event1)
emitter.on('someevent', event2)
emitter.emit('someevent')

Output:

node.js emit method

In the above image, you can see that the function event1 and event 2 has been registered by the name “someevent” using the on() method.

Next we used the emit method to fire the event and we can see the output of both the functions which means that both the functions were invoked as soon as the “someevent” event was fired.

Emitting event with parameter.

We can also pass data to the call back function. In order to do so we have to pass the data in the second argument of emit() method.

Code for event emitter with parameter:

const EventEmitter = require('events');
const emitter = new EventEmitter();
 
function event1(arg) {
    console.log('Welcome to', arg.name);
}
 
emitter.on('someevent', event1)
emitter.emit('someevent', { name: "DataFlair" })

Output:

nodejs pararmeter emit method

You can see that we have passed a name with value “DataFlair” in our second argument.This value is then used by the event1 function.

Event Emitter Methods:

Below are the methods present in the event emitter with explanation and code.

Detach Event:

We can detach the previously attached event by using the off() method.

Code for detaching event:

const EventEmitter = require('events');
const emitter = new EventEmitter();
 
function event1(arg) {
    console.log('Welcome to', arg.name);
}
 
emitter.on('someevent', event1)
emitter.emit('someevent', { name: "DataFlair" })
emitter.off('someevent', event1)
emitter.emit('someevent', { name: "DataFlair" })

Output

node.js detach method

You can see that we have used emit method twice to emit the same event but the output came only for that emit which was called before detaching the event using the off() method.

So once you detach an event then the emit method does not have any effect for that event.

Nodejs Count Listener:

listenerCount() method returns the number of listeners for that event. You can see in the below image that listenerCount() return 1 at first than as we called the off() method the listener for the event is detached and hence the count of listener is now zero.

Code for count listener:

const EventEmitter = require('events');
const emitter = new EventEmitter();
 
function event1(arg) {
    console.log('Welcome to', arg.name);
}
 
emitter.on('someevent', event1)
emitter.emit('someevent', { name: "DataFlair" })
console.log(emitter.listenerCount('someevent'))
emitter.off('someevent', event1)
emitter.emit('someevent', { name: "DataFlair" })
console.log(emitter.listenerCount('someevent'))

Output:

node.js listener count

Nodejs Raw Listener:

It returns an array of listeners for that particular event.

Code for raw listener:

const EventEmitter = require('events');
const emitter = new EventEmitter();
 
function event1(arg) {
    console.log('Welcome to', arg.name);
}
 
emitter.on('someevent', event1)
emitter.emit('someevent', { name: "DataFlair" })
console.log(emitter.rawListeners('someevent'))
emitter.off('someevent', event1)
emitter.emit('someevent', { name: "DataFlair" })
console.log(emitter.rawListeners('someevent'))

Output:

node.js raw listener

Before calling the off() method there was one listener so it returned its type and name.

After the off() method was called nothing was attached to the event so it returned an empty array.

Nodejs Add Listener:

This is similar to the on method. It takes the event name and a callback function and then attaches the event. It checks the event array to see if the event has already been attached or not. If the event is attached it returns the array, else return empty array.

Code for adding listener:

const EventEmitter = require('events');
const emitter = new EventEmitter();
 
function event1(arg) {
    console.log('Welcome to', arg.name);
}
 
emitter.addListener('someevent', event1)
emitter.emit('someevent', { name: "DataFlair" })

Output:

node.js addlistener

You can see that the result is same as the on() method

Remove Listener:

It is similar to the off() method. It checks in the event array for the event and it removes it from the event array.

Code for removing listener:

const EventEmitter = require('events');
const emitter = new EventEmitter();
 
function event1(arg) {
    console.log('Welcome to', arg.name);
}
 
emitter.addListener('someevent', event1)
emitter.emit('someevent', { name: "DataFlair" })
emitter.removeListener('someevent', event1);
emitter.emit('someevent', { name: "DataFlair" })

Output:

node.js removelistener

The answer is the same as that for the off() method.

Once() method in Nodejs:

If we want an event to be used only one time then we can use the once() method. It takes eventname and a callback function.

When the event is first emitted it invokes the callback function and after that it detaches the event automatically, after that it will not respond to any more emitted calls.

Code for once():

const EventEmitter = require('events');
const emitter = new EventEmitter();
function event1() {
    console.log('Welcome to DataFlair');
}
emitter.once('someevent', event1)
emitter.emit('someevent')
emitter.emit('someevent')

Output:

node.js once emitter

You can see that the once method invoked the callback function only when the first emit() method executed, the next emit method did not invoke the callback function as the event already got detached.

Summary

In this article we have seen the event loop of node js and built in methods of event emitter. We hope you enjoyed the article. Do check out DataFlair’s other blogs too.

Did you like this article? If Yes, please give DataFlair 5 Stars on Google

follow dataflair on YouTube

Leave a Reply

Your email address will not be published. Required fields are marked *