NestJS Logo

事件

Event Emitter包(@nestjs/event-emitter)提供了一个简单的观察者实现,允许您订阅和监听应用程序中发生的各种事件。事件作为应用程序各个方面解耦的很好方式,因为单个事件可以有多个不相互依赖的监听器。

EventEmitterModule在内部使用了eventemitter2包。

入门指南#

首先安装所需的包:


$ npm i --save @nestjs/event-emitter

安装完成后,将EventEmitterModule导入到根AppModule中,并像下面显示的那样运行forRoot()静态方法:

app.module.ts
JS TS

import { Module } from '@nestjs/common';
import { EventEmitterModule } from '@nestjs/event-emitter';

@Module({
  imports: [
    EventEmitterModule.forRoot()
  ],
})
export class AppModule {}

.forRoot()调用会初始化事件发射器并注册应用程序中存在的任何声明性事件监听器。注册发生在onApplicationBootstrap生命周期钩子发生时,确保所有模块都已加载并声明了任何预定的作业。

要配置底层的EventEmitter实例,请将配置对象传递给.forRoot()方法,如下所示:


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,
});

触发事件#

要调度(即触发)一个事件,首先使用标准构造函数注入来注入EventEmitter2


constructor(private eventEmitter: EventEmitter2) {}
提示@nestjs/event-emitter包中导入EventEmitter2

然后在一个类中使用它,如下所示:


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

监听事件#

要声明一个事件监听器,使用@OnEvent()装饰器在包含要执行的代码的方法定义之前进行修饰,如下所示:


@OnEvent('order.created')
handleOrderCreatedEvent(payload: OrderCreatedEvent) {
  // handle and process "OrderCreatedEvent" event
}
警告 事件订阅者不能是请求范围的。

第一个参数可以是一个字符串或符号,用于简单的事件发射器,也可以是一个字符串、符号或字符串、符号数组的组合,用于通配符发射器。第二个参数(可选)是一个监听器选项对象(阅读更多)。


@OnEvent('order.created', { async: true })
handleOrderCreatedEvent(payload: OrderCreatedEvent) {
  // handle and process "OrderCreatedEvent" event
}

要使用命名空间/通配符,将wildcard选项传递给EventEmitterModule#forRoot()方法。启用命名空间/通配符时,事件可以是由分隔符分隔的字符串(foo.bar),也可以是数组(['foo', 'bar'])。分隔符也可以作为配置属性(delimiter)进行配置。启用命名空间功能后,您可以使用通配符订阅事件:


@OnEvent('order.*')
handleOrderEvents(payload: OrderCreatedEvent | OrderRemovedEvent | OrderUpdatedEvent) {
  // handle and process an event
}

请注意,这样的通配符只适用于一个块。参数order.*将匹配例如order.createdorder.shipped这样的事件,但不会匹配order.delayed.out_of_stock。为了监听这样的事件,请使用多级通配符模式(即**),在EventEmitter2文档中有描述。

使用这个模式,您可以创建一个捕获所有事件的事件监听器。


@OnEvent('**')
handleEverything(payload: any) {
  // handle and process an event
}
提示EventEmitter2类提供了几个有用的方法来与事件交互,例如waitForonAny。您可以在这里阅读更多关于它们的信息。

示例#

可以在这里找到一个工作示例。

支持一下