How To Emit and Listen to Events Using The NestJS Event Emitter?
Events come in handy when we decouple parts of applications but need communication among them. In this post, we will look at how to use the NestJS Event Emitter.
Join the DZone community and get the full member experience.
Join For FreeMany times we need to decouple different parts of our application and still want communication between these parts. Events come in quite handy in such situations. In this post, we will look at how to use the NestJS Event Emitter.
NestJS has its own Event Emitter package. It provides a simple observer implementation. This allows us to subscribe and listen to various events.
So let’s dive right in.
1 – Installing the NestJS Event Emitter package
The first step is to actually install the required package in our project.
This can be done using the below command.
$ npm i --save @nestjs/event-emitter
Once the installation is successful, we need to import the package in the app.module.ts of our project. See the below example:
app.module.tsimport { Module } from '@nestjs/common';
import { EventEmitterModule } from '@nestjs/event-emitter';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { EventDemo } from './event.demo';
@Module({
imports: [EventEmitterModule.forRoot()],
controllers: [AppController],
providers: [AppService, EventDemo],
})
export class AppModule {}
Here, we import the EventEmitter in the imports array. The forRoot() call initializes the event emitter. It also registers any declarative event listeners that might exist within the application. If you wish to know more about modules, please read this detailed post about NestJS Module System.
We can also configure the EventEmitter instance by passing a configuration object to the .forRoot() function. See below:
EventEmitterModule.forRoot({
// set this to `true` to use wildcards
wildcard: false,
// the delimiter used to segment namespaces
delimiter: '.',
// set this to `true` if you want to emit the newListener event
newListener: false,
// set this to `true` if you want to emit the removeListener event
removeListener: false,
// the maximum amount of listeners that can be assigned to an event
maxListeners: 10,
// show event name in memory leak message when more than maximum amount of listeners is assigned
verboseMemoryLeak: false,
// disable throwing uncaughtException if an error event is emitted and it has no listeners
ignoreErrors: false,
});
2 – Dispatching Event using Event Emitter
To dispatch an event, we simply need to use the EventEmitter2 instance. We can do so by the constructor dependency injection.
See below code:
event.demo.tsimport { Injectable } from "@nestjs/common";
import { EventEmitter2 } from "@nestjs/event-emitter";
@Injectable()
export class EventDemo {
constructor(private eventEmitter: EventEmitter2){}
emitEvent() {
this.eventEmitter.emit('msg.sent', 'Hello World')
}
}
We create a class known as EventDemo and create a method emitEvent(). Basically, this method uses the EventEmitter instance and emits a simple Hello World message. Here, the first argument i.e. msg.sent is the event name. We can use this name to listen to events. The second argument is the payload. Here, we simply have a string. However, it can also be another object.
3 – Listening to the Event
The next step is to implement an appropriate listener for this event. We will create another method in the same EventDemo class.
event.demo.tsimport { Injectable } from "@nestjs/common";
import { EventEmitter2, OnEvent } from "@nestjs/event-emitter";
@Injectable()
export class EventDemo {
constructor(private eventEmitter: EventEmitter2){}
emitEvent() {
this.eventEmitter.emit('msg.sent', 'Hello World')
}
@OnEvent('msg.sent')
listentToEvent(msg: string) {
console.log('Message Received: ', msg)
}
}
We annotate the method using the @OnEvent() decorator. Basically, this decorator receives the event name as an argument. In this case, it is msg.sent. Then, it simply prints the message to the console.
If we want a certain category of events to be handled by this listener, we can use a wildcard as below:
@OnEvent('msg.*')
listentToEvent(msg: string) {
console.log('Message Received: ', msg)
}
This will match all events starting with msg. If we wish a particular listener to catch all events, we can use something like below:
@OnEvent('*.*')
listentToEvent(msg: string) {
console.log('Message Received: ', msg)
}
4 – Triggering the Event
For this example, we will trigger the event from the controller class as below:
app.controller.tsimport { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
import { EventDemo } from './event.demo';
@Controller()
export class AppController {
constructor(private readonly appService: AppService, private readonly eventDemo: EventDemo) {}
@Get()
sayHello() {
this.eventDemo.emitEvent();
}
}
Basically, this is a simple controller that uses the EventDemo instance to call the emitEvent() method. If you wish to know more about controllers, you can read this detailed post about NestJS Controllers.
Conclusion
With this, we have learned how to use NestJS Event Emitter. We implemented a basic event emitter and listener and also looked at the various approaches to configure listeners.
If you have any comments or queries on this topic, please feel free to write in the comments section below.
Published at DZone with permission of Saurabh Dashora. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments