Computer scienceBackendNode.jsCore ConceptsInternal modulesEventsEvents module basics

Intro to events module

7 minutes read

In this topic, we will touch on the asynchronous event-driven architecture of Node.js. We will consider such a pattern as an emitter and a listener for some events. Also, we will figure out a specific implementation of these patterns using the events module.

Event-driven model

First, you should understand that an event is a signal that something has happened. A named event (signal) can be generated by a special object called an emitter. Obviously, there must be special objects that react to these events, otherwise, the events will simply be ignored and nothing will happen. Objects that respond to events are called event listeners.

In fact, this model is quite simple. For example, consider an abstract example. When a person clicks on the submit button of the registration form, the event is a click on the button. Event listener register for a button click and then, for example, redirect you to a new page or pop up a modal window indicating that everything was sent successfully.

EventEmitter basic syntax

Let's look at the following simple example of using the event module:

const EventEmitter = require('node:events');

const myEmitter = new EventEmitter();

myEmitter.on('eventExample', () => {
  console.log('The event was detected!');
});

myEmitter.emit('eventExample');

Let's take a closer look at the above code. First, we imported the EventEmitter class from the events module.

We capitalized the EventEmitter because it is a class. With the help of this syntax, we understand that we have a class in front of us, and not a function or some kind of variable.

In the following lines, we have created an instance of the EventEmitter class. Then the most interesting part begins. With the on method, we add a listener function for the event named eventExample. We passed the name of the event as the first parameter and the callback (event handler) as the second one.

If we don't write the last line, nothing will happen. It's because the on method has just created an event listener, but no event has happened yet. In order to generate an event, you need to use the emit method. As the first argument, we passed the name of the event we want to trigger. The subsequent arguments are optional, but they can be passed if it is necessary.

It is in the above sequence that the on and emit methods should be used. If we emit an event first and then create an event listener, nothing will happen because the event was emitted before.

User logging

Let's look at a more complicated example where we have to log user data. Consider the following example:

const EventEmitter = require('node:events');

class LogEmitter extends EventEmitter {}

const logger = new LogEmitter();

logger.on('logging', (name) => {
    const date = new Date();
    console.log(`User ${name} was registered at ${date.toISOString()}`);
})

logger.emit('logging', 'Alex');

In this example, we have created our own LogEmitter class, which is inherited from the imported EventEmitter class. This is important for task decomposition, since creating multiple instances of the same EventEmitter class can cause emitters to work incorrectly. By creating a custom class, we separated the logic of logging from the rest of the program.

Also, in this case, we are passing the 'Alex' argument to the callback when using the emit method. The date constant is used to log not only the username but also the time, which is logical.

Executing this code will output the following:

User Alex was registered at 2022-10-22T10:31:37.174Z

Conclusion

In this topic, you've learned the principle of asynchronous event-driven architecture. You've also found out the practical application of the event listener and emitter patterns using the events module. In part, you have studied the use of a custom class, anticipating the problems of using multiple instances of the same class.

9 learners liked this piece of theory. 0 didn't like it. What about you?
Report a typo