Events

Any occurrence in node js is an event and the callback function is listener ( Function objects). Node js handle most of its core API in asynchronous event-driven architecture.

There are two type of events in Node JS, build-in events and custom events. build-in events are done on OS level and custom events on NodeJS.

Build-in events

The build-in events are handled by libuv, a C library to handle all I/O asynchronously in event loop. The build-in events are happened on OS level.

Build-in Event Example

file open


    const fs=require('fs');
    
    fs.ReadStream("./src/data.txt").on("open",()=>{
        console.log("file open");
    });

Custom Events

The custom events are handled by EventEmitter Class. Node JS has a build-in module to handle custom events. To load the module, use require('events').


const event=require('events');    

Event Emitter

The events module has a build in class EventEmitter. The instance of EventEmitter emits events and listners react to events.

Event Emitter class is used to emit events and subscribe to raise events. See an example of how to subscribe an event and then raise it.

Event Emitter Class


const event=require('events').EventEmitter;   
let emitter=new event();

// register listener or subscribe  
emitter.on('done',(res)=>{
    console.log(`event done with ${res} argument`);
});

// Raise, emit or trigger event
emitter.emit('done','hi');


let emitter is the new instance of EventEmitter class. To subscribe to event, use on function with event name a string and callback (listener). To raise event, use event.emit function with event name and argument to listener.


Multiple Subscribers for events

One of the main advantage of using events is having build-in support for multiple subscribers. We can listen multiple events at one time. See example

Event Emitter Class

subscriber 1

subscriber 2


const event=require('events').EventEmitter;   
let emitter=new event();

// subscribe     
emitter.on('done',()=>{
    console.log(`subscriber 1`);
});
// subscribe again
emitter.on('done',()=>{
    console.log(`subscriber 2`);
});

//Emit
emitter.emit('done');

All the listeners are called in order they are registered for event.

Argument in events

An argument passed in event is shared between all subscribers. See example.

subscriber 1 city is delhi

subscriber 2 city is delhi


const event=require('events').EventEmitter;   
let emitter=new event();

// subscribe     
emitter.on('done',(x)=>{
    console.log('subscriber 1 city is ', x);
});
// subscribe 
emitter.on('done',(x)=>{
    console.log('subscriber 2 city is', x);
});

//Emit
emitter.emit('done','delhi');

Check event is done

done

already done


const event=require('events').EventEmitter;
let emitter=new event();

emitter.on("done",(x)=>{
    console.log(`done`);
    x.handled=true;
})

emitter.on("done",(x)=>{
    if(x.handled){
        console.log(`already done`);
    }
});

emitter.emit('done',{handled:false});

Emit Event once

Once an event is subscribed, we can raise it any number of times. But to raise an event only once, EventEmitter provides a method once. once method raise or emit the listener only once. The next time emit method will not works. See example

event done 1


const event=require('events').EventEmitter;
let emitter=new event();

emitter.once("done",()=>{
    console.log("event done 1");
});

emitter.emit('done');                // will emit
emitter.emit('done');                // will not emit



Unsubscribe Event

To unsubscribe from an event, use removeListener function. This will ignore second emit as event is already unsubscribed. See example below.

handled


const event=require('events').EventEmitter;
let emitter=new event();

function eventHandler(){
    console.log(`handled`);
    
    // unsubscribe
    emitter.removeListener("done",eventHandler);
}

emitter.on('done',eventHandler);

emitter.emit('done');        // will emit
emitter.emit('done');        // will not emit



Error Event

To handle exceptions in node js, error event is used. Without error event, the default action is to print stack trace and then exit.


const event=require('events').EventEmitter;
let emitter=new event();

emitter.emit('error',new Error("Custom Error Message"));


Practical Example of Node JS Events

Lets assume a real scenario where a user will login and create account. First he will login and then his account will be created. To do this, we will use two modules (login.js) and (account.js) is our app src directory. See example

        /*server.js*/
const event=require('events').EventEmitter;
let emitter=new event();
module.exports=emitter;

var login=require('./login');
var account=require('./account');

emitter.emit('login',9);
emitter.emit('account');
        /*login.js*/
var t=require('./server');

t.on("login",(res)=>{
    console.log("Login process starts at",res)
});
t.on("login",(res)=>{
    console.log("login process done");
})
        /*account.js*/
var t=require('./server');

t.once("account",(res)=>{
    console.log("account process done");
});

Output

Login process starts at 9

login process done

account process done