Create and consume event emitters
Posted
Updated
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.
💰 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.
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 EventEmitter
is inheritance. Look at this article for a refresher on Inheritance in Javascript.
class MyEmitter extends EventEmitter {
constructor(opts = {}) {
super(opts);
this.name = opts.name;
}
}
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');
}
}
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
.
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.
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.
eventEmitter
is a constructor method.emit
method has to be used with an event name as an argument.on
or addEventListener
can be used with the event name.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):
Never miss an article.