JavaScript

The event loop (queue)

We know JavaScript is a single threaded language and executed line by line which makes it synchronous. Since Node is based in JavaScript, it inherits this single-threaded synchronous behavior.

So, if you have functionality that needs to wait on something, such as opening a file, retrieving data from the database, a web response, or other activity of this nature, then blocking the application until the operation is finished would be a major point of failure in a server-based application. The solution to prevent blocking is the event loop.

What is event loop

The event-loop is an infinite loop that in each iteration verifies in the event queue if some event was triggered. When an event is triggered, the event-loop executes it and sends it to the queue of executed events. When an event is running, we can write any logic on it using the callback function.

Node has its own event loop which is used to help facilitate server-based functionality, primarily file system’s input/output (I/O). This includes events associated with:

  • Opening a file
  • Reading file content
  • Waiting for a web-based request from a user (similar to AJAX request)

Not only are these types of processes potentially time-consuming, but there can also be a lot of contention for resources, and each access of the resource typically locks the resource from other access until the original process is finished.

Node processes all of the events in the queue, in order, when it gets to the event you’re interested in, it invokes the callback function you’ve provided, passing in any information associated with the event.

const fs = require ('fs')

fs.readFile('./a_file.txt', callback)

function callback (err, data) {
 //This function executes when
 //the file content is available
}

The EventEmitter

The EventEmitter class allows us to register one or more functions as listeners, which will be invoked when a particular event type is fired. To demonstrate its core functionality, we’ll try a quick test application. First, include the Events module:

const events = require('events')

Next, create an instance of EventEmitter:

const emitter = new events.EventEmitter()

The essential methods of the EventEmitter are given as follows:

EventEmitter.on (event, listener)

This method invoked when a specific event is emitted. This method accepts two parameters, the first parameter is the name of the event and the second, a callback function to register a new listener.

For consistency with browser-based JavaScript, EventEmitter.on and element.addListener are interchangeable.

EventEmitter.once (event, listener)

This method registers a new listener, which is then removed after the event is emitted for the first time.

EventEmitter.emit (event, [arg1],[args...])

This method produces a new event and provides additional arguments to be passed to the listeners.

EventEmitter.removeListener(event, listener)

This method removes a listener for the specified event type.

The EventEmitter Example

A simple application that triggered an event using EventEmitter.emit method and then EventEmitter.on method used to listen that event.

const events = require('events');
const emitter = new events.EventEmitter();
var counter = 0;

setInterval( () => {
 counter++;
 //produce a new event, named 'increased'
 emitter.emit('increased', counter);
}, 5000)

//listen the 'increased' event
emitter.on('increased', (num) => {
 console.log(num);
})

Extending the above example

const events = require('events');
const emitter = new events.EventEmitter();
var counter = 0;

setInterval( () => {
 counter++;
 //produce a new event, named 'increased'
 emitter.emit('increased', counter);
}, 5000)

setInterval( () => {
 counter--;
 //produce a new event, named 'decreased'
 emitter.emit('decreased', counter);
}, 8000)

//listen the 'increased' event
emitter.on('increased', (num) => {
 console.log('increased:' +num);
})

//listen the 'decreased' event
emitter.on('decreased', (num) => {
 console.log('decreased:' +num);
})

In next tutorial we’ll create a file walker class by extending the EventEmitter class.