How do Nodes.js Events Emitter Modules Efficiently Work

node-js

Node.js are event-driven applications, and the event itself exhibits its meaning that something like “happen” or “occur” so far. Events in Node.js are just like the concepts of the callback function in Node.js. So, we can say that it’s an event-driven module specific to asynchronous architecture. This executes the Node.js events module for conditions that don’t have it, similar to programs. 

Any object that emits events is supposed to be an instance of the EventEmitter class. These objects reveal an eventEmitter.on() function which permits one or more functions to be connected to named events emitted by the object. Generally, event names are camel-cased strings, yet any valid JavaScript property key can be used.

So, let’s move on to figure out some events modules of the Event Emitter class, which is a specific key of working with Node.js events.

Grab the Most Useful Methods of Node.js Events Module

The event listener has the following intrinsic events:

  • As a listener is added – newListener 
  • As a listener is removed – removeListener

When the EventEmitter object emits an event, each function that appends to that specific event is called synchronous. Any values remitted by the called listeners are ignored and discarded.

There are some specific steps of Node.js events that show a simple EventEmitter instance with a single listener. In this example.

  • The eventEmitter.on() method is specific to register listeners
  • The eventEmitter.emit() method is specific to trigger the event.

const EventEmitter = require(‘events’).

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();

myEmitter.on(‘event’, () => {

  console.log(‘an event occurred!’);

});

myEmitter.emit(‘event’);

Passing Arguments and this to Listeners

The eventEmitter.emit() method exhibits a random set of arguments in order to pass to the listener functions. Remember that as an ordinary listener function is called, the standard of this keyword is deliberately set to reference the EventEmitter instance to which the listener is attached.

const myEmitter = new MyEmitter();

myEmitter.on(‘event’, function(a, b) {

  console.log(a, b, this, this === myEmitter);

  // Prints:

  //   a b MyEmitter {

  //     domain: null,

  //     _events: { event: [Function] },

  //     _eventsCount: 1,

  //     _maxListeners: undefined } true

});

myEmitter.emit(‘event’, ‘a’, ‘b’);

Asynchronous & Synchronous

The EventEmitter calls all listeners synchronously as in the same order in which they were registered. Such practice assures the proper sequencing of events and provides assistance to avoid race conditions and logic errors. As an appropriate and more suitable, listener functions can switch to an asynchronous mode of operation using the setImmediate() or process.nextTick() methods:

const myEmitter = new MyEmitter();

myEmitter.on(‘event’, (a, b) => {

  setImmediate(() => {

    console.log(‘this happens asynchronously’);

  });

});

myEmitter.emit(‘event’, ‘a’, ‘b’);

Handling Events only Once

When a listener is registered using the eventEmitter.on() method, that listener is implored any time the named event is emitted.

const myEmitter = new MyEmitter();

let m = 0;

myEmitter.on(‘event’, () => {

  console.log(++m);

});

myEmitter.emit(‘event’);

// Prints: 1

myEmitter.emit(‘event’);

// Prints: 2

By moving with the eventEmitter.once() technique, it is feasible to register a listener that is called when it’s mostly considered for a particular event. As the event is emitted, the listener is uncataloged and then called.

const myEmitter = new MyEmitter();

let m = 0;

myEmitter.once(‘event’, () => {

  console.log(++m);

});

myEmitter.emit(‘event’);

// Prints: 1

myEmitter.emit(‘event’);

// Ignored

Also Read: Project-Based Learning – Best Practices

Error Events

As any error occurs within an EventEmitter instance, there is an ‘error’ event to be emitted as a typical action happens in this respect. These errors are specifically treated within Node.js.

On the off chance that an EventEmitter does not have at least one listener registered for the ‘error’ event, an ‘error’ event is emitted; the error is tossed, a stack trace or follow is printed, and the Node.js process exits.

const myEmitter = new MyEmitter();

myEmitter.emit(‘error’, new Error(‘whoops!’));

// Throws and crashes Node.js

It is feasible to screen ‘error’ events without consuming the emitted error by installing a listener via the symbol of events.errorMonitor.

const { EventEmitter, errorMonitor } = require(‘events’);

const myEmitter = new EventEmitter();

myEmitter.on(errorMonitor, (err) => {

  MyMonitoringTool.log(err);

});

myEmitter.emit(‘error’, new Error(‘whoops!’));

// Still throws and crashes Node.js

Capture Rejections

Being the event handlers, it is problematic to use async functions. The main concern is that it leads to an unhandled rejection in the event of a thrown exception:

const ee = new EventEmitter();

ee.on(‘something’, async (value) => {

  throw new Error(‘kaboom’);

});

The capture rejections option in the EventEmitter constructor or the setting as worldwide alters this behavior, installing a. then (undefined, handler) handler on the Promise.

This handler directs the exception asynchronously to the symbol. For(‘nodejs.rejection’) method, if there is one, or two ‘error’ event handlers if there is none.

const ee1 = new EventEmitter({ captureRejections: true });

ee1.on(‘something’, async (value) => {

  throw new Error(‘kaboom’);

});

ee1.on(‘error’, console.log);

const ee2 = new EventEmitter({ captureRejections: true });

ee2.on(‘something’, async (value) => {

  throw new Error(‘kaboom’);

});

ee2[Symbol.for(‘nodejs.rejection’)] = console.log;

Event Emitter Class

The Node.js events emitter is confined with the event module, being exposed by it. As new listeners are added, all the EventEmitters emit the event ‘newListener.’ While on removing the existing listeners, they emit ‘removeListener.’

Event: ‘newListener’

Prior to a listener being added to its internal exhibit of listeners, the EventEmitter instance will emit its own ‘newListener’ event. 

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();

// Only do this once so we don’t loop forever

myEmitter.once(‘newListener’, (event, listener) => {

  if (event === ‘event’) {

    // Insert a new listener in front

    myEmitter.on(‘event’, () => {

      console.log(‘B’);

    });

  }

});

myEmitter.on(‘event’, () => {

  console.log(‘A’);

});

myEmitter.emit(‘event’);

// Prints:

//   B

//   A

Event: ‘removeListener’

removeListener() will probably remove one instance of a listener from the listener array. When a single listener has been added for the specified eventName more than one times to the listener array, then removeListener() will be called multiple times in order to remove each instance.

const myEmitter = new MyEmitter();

const callbackA = () => {

  console.log(‘A’);

  myEmitter.removeListener(‘event’, callbackB);

};

const callbackB = () => {

  console.log(‘B’);

};

myEmitter.on(‘event’, callbackA);

myEmitter.on(‘event’, callbackB);

// callbackA removes listener callbackB but it will still be called.

// Internal listener array at time of emit [callbackA, callbackB]

myEmitter.emit(‘event’);

// Prints:

//   A

//   B

// callbackB is now removed.

// Internal listener array [callbackA]

myEmitter.emit(‘event’);

// Prints:

//   A

Ending Note

In the whole guide, you got enough about how Node.js events emitter modules work. You emitted Node.js events with the emit() function of an EventEmitter object, then listened to events with the newListener() andremoveListener() functions in order to execute code every time the event is set off. 

Works Cited

https://nodejs.org/en/. (n.d.). From nodejs : https://nodejs.org/en/

Leave a Reply

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