Passer au contenu

Émettre et écouter des événements avec NestJS

Événements

Le package Event Emitter (@nestjs/event-emitter) fournit une simple implémentation d’observateur, vous permettant de vous abonner et d’écouter divers événements qui se produisent dans votre application. Les événements servent de moyen idéal pour découpler divers aspects de votre application, puisqu’un seul événement peut avoir plusieurs auditeurs qui ne dépendent pas les uns des autres.

Le EventEmitterModule utilise en interne le package eventemitter2.

Commencer

Tout d’abord, installez le package requis :

Fenêtre de terminal
$ npm i --save @nestjs/event-emitter

Une fois l’installation terminée, importez le EventEmitterModule dans le module racine AppModule et exécutez la méthode statique forRoot() comme indiqué ci-dessous :

app.module.ts
import { Module } from '@nestjs/common';
import { EventEmitterModule } from '@nestjs/event-emitter';
@Module({
imports: [
EventEmitterModule.forRoot()
],
})
export class AppModule {}

L’appel à .forRoot() initialise l’émetteur d’événements et enregistre tous les auditeurs d’événements déclaratifs qui existent dans votre application. L’enregistrement se produit lorsque le hook de cycle de vie onApplicationBootstrap se produit, garantissant que tous les modules ont été chargés et ont déclaré les tâches programmées.

Pour configurer l’instance EventEmitter sous-jacente, passez l’objet de configuration à la méthode .forRoot(), comme suit :

EventEmitterModule.forRoot({
// définissez ceci sur `true` pour utiliser des jokers
wildcard: false,
// le séparateur utilisé pour segmenter les espaces de noms
delimiter: '.',
// définissez ceci sur `true` si vous souhaitez émettre l'événement newListener
newListener: false,
// définissez ceci sur `true` si vous souhaitez émettre l'événement removeListener
removeListener: false,
// le nombre maximum d'auditeurs pouvant être assignés à un événement
maxListeners: 10,
// afficher le nom de l'événement dans le message de fuite de mémoire lorsque plus que le nombre maximum d'auditeurs est assigné
verboseMemoryLeak: false,
// désactiver le lancement d'uncaughtException si un événement d'erreur est émis et qu'il n'a pas d'auditeurs
ignoreErrors: false,
});

Émettre des événements

Pour émettre (c’est-à-dire, déclencher) un événement, injectez d’abord EventEmitter2 en utilisant l’injection de constructeur standard :

constructor(private eventEmitter: EventEmitter2) {}

Ensuite, utilisez-le dans une classe comme suit :

this.eventEmitter.emit(
'order.created',
new OrderCreatedEvent({
orderId: 1,
payload: {},
}),
);

Écouter des événements

Pour déclarer un auditeur d’événements, décorez une méthode avec le décorateur @OnEvent() précédant la définition de la méthode contenant le code à exécuter, comme suit :

@OnEvent('order.created')
handleOrderCreatedEvent(payload: OrderCreatedEvent) {
// gérer et traiter l'événement "OrderCreatedEvent"
}

Le premier argument peut être une string ou un symbol pour un émetteur d’événements simple et un string | symbol | Array<string | symbol> dans le cas d’un émetteur de jokers.

Le deuxième argument (optionnel) est un objet d’options d’auditeur comme suit :

export type OnEventOptions = OnOptions & {
/**
* Si "true", préfixe (au lieu d'ajouter) l'auditeur donné au tableau des auditeurs.
*
* @see https://github.com/EventEmitter2/EventEmitter2#emitterprependlistenerevent-listener-options
*
* @default false
*/
prependListener?: boolean;
/**
* Si "true", le callback onEvent ne lancera pas d'erreur lors du traitement de l'événement. Sinon, si "false", cela lancera une erreur.
*
* @default true
*/
suppressErrors?: boolean;
};
@OnEvent('order.created', { async: true })
handleOrderCreatedEvent(payload: OrderCreatedEvent) {
// gérer et traiter l'événement "OrderCreatedEvent"
}

Pour utiliser les espaces de noms/jokers, passez l’option wildcard à la méthode EventEmitterModule#forRoot(). Lorsque les espaces de noms/jokers sont activés, les événements peuvent être des chaînes (foo.bar) séparées par un délimiteur ou des tableaux ([‘foo’, ‘bar’]). Le délimiteur est également configurable en tant que propriété de configuration (delimiter). Avec la fonctionnalité d’espace de noms activée, vous pouvez vous abonner aux événements en utilisant un joker :

@OnEvent('order.*')
handleOrderEvents(payload: OrderCreatedEvent | OrderRemovedEvent | OrderUpdatedEvent) {
// gérer et traiter un événement
}

Notez qu’un tel joker ne s’applique qu’à un seul bloc. L’argument order.* correspondra, par exemple, aux événements order.created et order.shipped mais pas à order.delayed.out_of_stock. Pour écouter de tels événements, utilisez le modèle de wildcard multiple (c’est-à-dire, **), décrit dans la documentation d’EventEmitter2.

Avec ce modèle, vous pouvez, par exemple, créer un auditeur d’événements qui capture tous les événements.

@OnEvent('**')
handleEverything(payload: any) {
// gérer et traiter un événement
}

Exemple

Un exemple fonctionnel est disponible ici.