事件
事件发射器包
(@nestjs/event-emitter
)提供了一个简单的观察者实现,
允许您订阅和监听应用程序中发生的各种事件。
事件作为解耦应用程序各个方面的绝佳方式,因为单个事件可以有多个监听器,它们彼此不依赖。
EventEmitterModule
内部使用了 eventemitter2 包。
入门
首先安装所需的包:
npm i --save @nestjs/event-emitter
安装完成后,将 EventEmitterModule
导入到根 AppModule
中,
并像下面展示的那样运行 forRoot()
静态方法:
import { Module } from '@nestjs/common';
import { EventEmitterModule } from '@nestjs/event-emitter';
@Module({
imports: [
EventEmitterModule.forRoot()
],
})
export class AppModule {}
.forRoot()
调用初始化事件发射器并注册应用程序中存在的任何声明式事件监听器。
注册发生在 onApplicationBootstrap
生命周期钩子发生时,确保所有模块都已加载并声明了任何计划的任务。
要配置底层的 EventEmitter
实例,请将配置对象传递给 .forRoot()
方法,如下所示:
EventEmitterModule.forRoot({
wildcard: false, // 将其设置为 `true` 以使用通配符
delimiter: '.', // 用于分隔命名空间的分隔符
newListener: false, // 如果要发射 newListener 事件,请将其设置为 `true`
removeListener: false, // 如果要发射 removeListener 事件,请将其设置为 `true`
maxListeners: 10, // 可以分配给一个事件的最大侦听器数量
verboseMemoryLeak: false, // 当分配给事件的侦听器超过最大数量时,在内存泄漏消息中显示事件名称
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) {
// 处理并处理 "OrderCreatedEvent" 事件
}
事件订阅者不能具有请求范围。
第一个参数可以是一个string
或symbol
,用于简单事件发射器,
以及在通配符发射器的情况下是一个string | symbol | Array<string | symbol>
。
第二个参数(可选)是一个监听器选项对象,如下所示:
export type OnEventOptions = OnOptions & {
prependListener?: boolean; // 如果为 "true",将给定的监听器前置(而不是追加)到监听器数组中
suppressErrors?: boolean; // 如果为 "true",在处理事件时 onEvent 回调将 不会抛出错误。否则,如果为 "false",它将抛出错误。
};
阅读有关 OnOptions
选项对象的更多信息,请参阅 eventemitter2 的文档。
@OnEvent('order.created', { async: true })
handleOrderCreatedEvent(payload: OrderCreatedEvent) {
// 处理并处理 "OrderCreatedEvent" 事件
}
要使用命名空间/通配符,将 wildcard
选项传递到 EventEmitterModule#forRoot()
方法中。
启用命名空间/通配符时,事件可以是由分隔符分隔的字符串(foo.bar
),也可以是数组(['foo', 'bar']
)。
分隔符还可以作为配置属性(delimiter
)进行配置。启用命名空间功能后,可以使用通配符订阅事件:
@OnEvent('order.*')
handleOrderEvents(payload: OrderCreatedEvent | OrderRemovedEvent | OrderUpdatedEvent) {
// 处理和处理事件
}
请注意,这样的通配符仅适用于一个块。参数 order.*
将匹配例如事件 order.created
和 order.shipped
,
但不匹配 order.delayed.out_of_stock
。
为了监听这样的事件,请使用 EventEmitter2
文档中描述的多级通配符模式(即 **
)。
使用这种模式,您可以创建一个捕获所有事件的事件监听器,例如:
@OnEvent('**')
handleEverything(payload: any) {
// 处理和处理事件
}
EventEmitter2
类提供了一些有用的方法来与事件交互,例如 waitFor
和 onAny
。
您可以在这里阅读更多关于它们的信息。
示例
一个可运行的示例在 这里。