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?
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 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;
}
}
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
oraddEventListener
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):
Top comments (0)