Event Loop & Event Emitters in Node.js

    0 Votes

We has started this tutorial series by saying that NodeJS is extremely fast. But have you thought why is this so? Even after being a single threaded environment, it beats python and ruby frameworks by many times. This article tries to explain why this is. What makes JavaScript fast…!! So hold on.

Event Loop

Event loop is loop in NodeJS environment which runs in background checking for various events and callback functions to execute. Understand it this way.

Assume NodeJS is the name of a restaurant. You are the client and you enter the restaurant and get seated. A waiter comes to you and asks what you want. You ask him for a bottle of water, one pasta and one pizza. The waiter will then tell other servers what to do. He will tell one server to get a bottle of water, one chef to cook pasta and another chef to cook pizza. If no one is free then the command is queued with the respective person. After taking this order he goes to other customer and takes their order.

The server who went to fetch a bottle of water comes back and informs the waiter that he is done and waits for the waiter to finish taking the current order. Then he hands over the bottle to the waiter who delivers it to you. Meanwhile the pasta is still being cooked and pizza is ready to server. The chef informs the waiter about the pizza and he delivers the pizza freeing up the pizza chef. Finally the pasta is finished and passed on to the waiter. When all the servers and chefs are finished with their work AND no more clients are to come, the restaurant is shut down.

This is how this will look like

event loop example

In a similar way when a client connects to a NodeJS process, the process is greeted by the main thread (manager) which takes all the functions and assigns them worker threads as required. If no worker thread is available, then the request is queued till a worker thread is available to process the request. NodeJS architecture has a set of worker threads in its internal thread pool (size can be changed) to handle blocking tasks in the background while the main thread is interacting with the clients.

While the many worker threads are doing their function, another thread, the event loop, runs in background scanning all the worker threads for their result. If a particular worker thread has finished executing, then the callback function passed to the worker thread is called by the event loop which may again transfer the function to another worker thread, or if no callbacks are left then the output is produced.

Once a worker thread has finished executing, the thread is killed and sent back to the internal thread pool for reuse by some other function. The event loop while scanning for the results also keeps track of the number of threads in use. If no worker thread is being used and the main thread has stopped receiving any input, the the Node process is terminated.

Since the thread which is interacting with the clients is not involved in any processing, the number of clients a NodeJS server can accept is much higher than traditional Apache, Ruby on Rails or Django servers.

Events

In the previous section we talked about how the event loop keeps scanning the worker thread for results. But how exactly does the event loop know when a result has been produced? The answer is events. Events are building blocks of NodeJS architecture which was developed as an event-driven server structure.

Events are some changes or signals which are emitted by the worker threads to let the event loop know that a particular event has occurred. In the above restaurant example events can be imagined as a mechanism by which the chef and servers are signalling the waiter that their job is finished.

An algorithm for the event loop can be simplified as:

  1. Listen for any calls (events)

  2. If any thread is calling then attend the thread.

  3. Process the result

  4. Go to step 1

Algorithm for our waiter:

  1. Manager assigns a waiter to listen to “bottle”, “pasta” and “pizza” events

  2. Scan for events

  3. If no event, go to step 2

  4. waiter on “bottle” event

    1. Fetch the bottle

    2. Serve it to the client

  5. waiter on “pasta” event

    1. Server pasta to the client

  6. waiter on “pizza” event

    1. Slice the pizza

    2. Serve it to the client

  7. Go to step 2

One problem which algorithm is that even after the events are done, the waiter still keeps listening to events. To solve this the manager needs to tell the waiter to stop listening to particular events.

This is all about events. Now let’s write some code.

Knock Knock Application

"use strict"; 
const events = require('events');
const emitter = new events.EventEmitter();
let doorKnockListner = function() 
{
	console.log("Knock Knock");
}
let phoneRingListner = function() 
{
	console.log("Phone Ringing");
}
emitter.addListner("door", doorKnockListner);
emitter.addListner("phone", phoneRingListner);

Create a new index.js file in your project directory with the following lines

This simple code is to demonstrate the functioning of events in NodeJS. To use events in NodeJS we need to use the b>events module, a core NodeJS module, to listen and emit events. From the events module, we need specifically EventEmitter object which will handle the events for us.

We define two different functions - doorKnockListener & phoneRingListener, which are the functions to be executed when a particular event is captured by the event loop. After declaring the listener functions, we need to assign these functions to particular events so that the event loop can trigger the right functions for the right events.

We add listeners to events using emitter.addListener(eventName, callback) where the eventName is an alphanumeric string. Here we make doorKnockListener function to react to door event and phoneRingListener to execute on phone event. Note that events are CASE SENSITIVE - Door event is not the same as door event.

Finally there would be something that would actually emit this event. So we emit the door event.

event output

The output

As you can see, on emitting the door event, the doorKnockListener is called and executed. Since the phone event was not emitted hence the phoneRingListener is never executed.

Once the event is emitted and executed, the event loop still keeps listening for these events until you remove the listener. See the example below.

"use strict"; 
const events = require('events');
const emitter = new events.EventEmitter();
let doorKnockListner = function() 
{
	console.log("Knock Knock");
}
let phoneRingListner = function() 
{
	console.log("Phone Ringing");
}
emitter.addListner("door", doorKnockListner);
emitter.addListner("phone", phoneRingListner);

emitter.emit("door");
console.log("Person 1 entered");
emitter.emit("door");
console.log("Person 2 entered, Person 3 is at door");

emitter.removeListner("door", doorKnockListner);
emitter.emit("door");

event emitter output

After the door event is emitted for the first time (line 17), the event loop still listens for the event. So when the door event is emitted again in line 19, again the doorKnockListener is called. The listener is removed in the next line using emitter.removeListener(eventName, callback) and then if the event is emitted, the callback function is not executed.

You can even attach multiple listeners for the same event. Try changing the code of index.js as (see line no.s for change)

Here we assign phoneRingListener and doorKnockListener to the same door event.

event listner

When the door event is emitted, both the listeners are called in the order of assigment.

event listner output

There are many uses of events in NodeJS apart from internal events. For example, the process global object emits and listens to many useful events like:

  1. exit
    This event is emitted whenever a NodeJS process is exiting i.e. terminating.

  2. uncaughtException
    This event is emitted whenever a NodeJS process throws an Error which is not caught by the try-catch block.

  3. Signal events like - SIGINT, SIGBREAK, SIGKILL etc
    These events are emitted whenever user provides a signal to the NodeJS process by the use of keyboard controls like Ctrl+D or Ctrl+C etc.

  4. Many other events which are not much used but can be found in the official documentation of NodeJS.

That is everything about event loop and event emitters in NodeJS.

Popular Videos

communication

How to improve your Interview, Salary Negotiation, Communication & Presentation Skills.

Got a tip or Question?
Let us know

Related Articles

Node.js Introduction & Environment Setup
Node Package Manager (NPM)
Global Variables in Node.js
Node.js Callbacks
Node.js Buffers and Streams
Node.js File System & Setting up File Structure