Event Emitters in Node.js
© https://nodejs.org/en/

Event Emitters in Node.js

Create and consume event emitters

By Mario Kandut

Europe’s developer-focused job platform

Let companies apply to you

Developer-focused, salary and tech stack upfront.

Just one profile, no job applications!

This article is based on Node v16.14.0.

On the frontend-side of an application the user interactions are handled through events, click events, keyboard events, mouse moving events, etc. In Node.js (backend-side) we can build a similar system using the events module.

What is the Event Emitter?

💰 The Pragmatic Programmer: journey to mastery. 💰 One of the best books in software development, sold over 200,000 times.

Much of the Node.js core API is built around event-driven architecture. There objects or emitters emit events that cause a function object or listener to be called. For example, HTTP and TCP servers are an event emitter, a TCP socket is an event emitter, HTTP request and response objects are event emitters.

All objects that emit events are instances of the EventEmitter class and expose an eventEmitter.on() function so functions can be attached to the named events. Event names are typically camel-cased.

Creating an Event Emitter

The events module exports an EventEmitter constructor, depending on the Node version the events module is the EventEmitter or you have to deconstruct it.

const EventEmitter = require('events');

The EventEmitter is a constructor and to create a new event emitter the constructor has to be called with the new keyword.

const myEmitter = new EventEmitter();

A common usage pattern with EventEmitteris inheritance. Look at this article for a refresher on Inheritance in Javascript.

class MyEmitter extends EventEmitter {
  constructor(opts = {}) {
    super(opts);
    this.name = opts.name;
  }
}

Emitting Events

The created EventEmitter object exposes two methods - on and emit.

  • emit is used to trigger an event.
  • on is used to add a callback function.

To emit an event the emit method has to be called:

const EventEmitter = require('events');
const myEmitter = new EventEmitter();
myEmitter.emit('event');

The first argument of emit is the event namespace. We need to know the event namespace to be able to listen to emitted events.

The eventEmitter.emit() method allows an arbitrary set of arguments to be passed to the listener functions, like myEmitter.emit('event', 'a', 'b');

The following example emits an error event and a close event when the method destroy is called with an error.

const EventEmitter = require('events')
class MyEmitter extends EventEmitter {
  constructor (opts = {}) {
    super(opts);
    this.name = opts.name;
  },
  destroy (err) {
    if (err) { this.emit('error', err) }
    this.emit('close');
  }
}

Listening for Events

To listen to an emitted event the event emitter object has a method addListener or the alias on.

Copy the following code in the Node REPL and execute.

const EventEmitter = require('events');

const eventEmitter = new EventEmitter();
eventEmitter.on('close', () => {
  console.log('close event fired!');
});
eventEmitter.emit('close');

The output will be close event fired!.

Arguments passed to emit are received by the listener.

For example:

const EventEmitter = require('events');

const eventEmitter = new EventEmitter();
eventEmitter.on('add', (a, b) => {
  console.log('add event fired!');
  console.log(a + b);
});
eventEmitter.emit('add', 1, 2);

Ordering is important. Event listeners will not react to events if the event is emitted before the listener is added. Event listeners are also called in the order they are registered.

const EventEmitter = require('events');
const eventEmitter = new EventEmitter();
eventEmitter.on('my-event', () => {
  console.log('1st');
});
eventEmitter.on('my-event', () => {
  console.log('2nd');
});
eventEmitter.emit('my-event');

The output from the code above will be 1st and then 2nd.

There is a method which can be used to inject listeners to the top prependListener.

const EventEmitter = require('events');
const eventEmitter = new EventEmitter();
eventEmitter.on('my-event', () => {
  console.log('1st');
});
eventEmitter.prependListener('my-event', () => {
  console.log('2nd');
});
eventEmitter.emit('my-event');

Now the output will be 2nd and then 1st.

Single Use Listener

An event can also be emitted more than once. To reduce this the once method can be used. It removes its listener after it has been called.

const EventEmitter = require('events');
const eventEmitter = new EventEmitter();
eventEmitter.once('event', () => {
  console.log('event fired');
});
eventEmitter.emit('event');
eventEmitter.emit('event');

The output event fired will only be logged once.

Removing Listeners

Listeners can be removed with the removeListener method. It takes two arguments the event name, and the listener function.

const callback = stream => {
  console.log('someone connected!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback);

removeListener() will remove, at most, one instance of a listener from the listener array. If a single listener has been added multiple times for the specified eventName, then removeListener() must be called multiple times to remove each instance.

The removeAllListeners method can be used to remove listeners without having a reference to their function. It takes one optional argument, the event name. It is useful if multiple listener for the same event name have been registered.

Emitting an error event on an event emitter will cause the event emitter to throw an exception if a listener for the error event has not been registered.

TL;DR

  • The Node.js core API is built around event-driven architecture.
  • The eventEmitter is a constructor method.
  • To emit events the emit method has to be used with an event name as an argument.
  • To listen to events the alias on or addEventListener can be used with the event name.
  • The event name should be camelCased.

Thanks for reading and if you have any questions, use the comment function or send me a message @mariokandut.

If you want to know more about Node, have a look at these Node Tutorials.

References (and Big thanks):

JSNAD - Linux Foundation, Node.js Docs, Nodejs.dev,

More node articles:

How to create a web server in Node.js

How to dynamically load ESM in CJS

How to convert a CJS module to an ESM

How to create a CJS module

How to stream to an HTTP response

How to handle binary data in Node.js?

How to use streams to ETL data?

How to connect streams with pipeline?

How to handle stream errors?

How to connect streams with pipe?

What Is a Node.js Stream?

Handling Errors in Node (asynchronous)

Handling Errors in Node.js (synchronous)

Introduction to errors in Node.js

Callback to promise-based functions

ETL: Load Data to Destination with Node.js

ETL: Transform Data with Node.js

ETL: Extract Data with Node.js

Event Emitters in Node.js

How to set up SSL locally with Node.js?

How to use async/await in Node.js

What is an API proxy?

How to make an API request in Node.js?

How does the Event Loop work in Node.js

How to wait for multiple Promises?

How to organize Node.js code

Understanding Promises in Node.js

How does the Node.js module system work?

Set up and test a .env file in Node

How to Use Environment Variables in Node

How to clean up node modules?

Restart a Node.js app automatically

How to update a Node dependency - NPM?

What are NPM scripts?

How to uninstall npm packages?

How to install npm packages?

How to create a package.json file?

What Is the Node.js ETL Pipeline?

What is data brokering in Node.js?

How to read and write JSON Files with Node.js?

What is package-lock.json?

How to install Node.js locally with nvm?

How to update Node.js?

How to check unused npm packages?

What is the Node.js fs module?

What is Semantic versioning?

The Basics of Package.json explained

How to patch an NPM dependency

What is NPM audit?

Beginner`s guide to NPM

Getting started with Node.js

Scroll to top ↑