NestJS中如何让注入了服务的Listener正常监听事件?
问题根因
你遇到的问题本质是依赖注入链路断裂,导致ClientUpdatedListener没有被NestJS的DI容器正常实例化,因此@OnEvent装饰器没有生效,自然无法接收事件:
- 移除构造函数注入时,
ClientUpdatedListener不需要解析其他依赖,可以正常被实例化,所以功能正常 - 添加注入后,只要依赖链上任意一个服务无法被正常实例化,
ClientUpdatedListener就会初始化失败,无法注册事件监听
修复步骤
1. 检查模块的Providers注册配置
你必须把ClientUpdatedListener、NotificationsService以及两个服务依赖的所有注入令牌都注册到对应模块的providers数组中,示例配置如下:
import { Module } from '@nestjs/common'; import { EventEmitterModule } from '@nestjs/event-emitter'; import { ClientUpdatedListener } from './client-updated.listener'; import { NotificationsService } from './notifications.service'; import { TENANT_CONNECTION } from './your-tenant-constant'; // 替换为你实际的常量文件路径 @Module({ // 根模块已经导入过EventEmitterModule则不需要重复导入 imports: [EventEmitterModule.forRoot()], providers: [ ClientUpdatedListener, // 必须注册监听器,否则DI不会实例化它 NotificationsService, // 必须注册被依赖的通知服务 // 必须提供TENANT_CONNECTION对应的实例,否则NotificationsService初始化失败 { provide: TENANT_CONNECTION, useFactory: () => { // 替换为你实际的租户数据库连接生成逻辑 return getTenantDbConnection(); } } ] }) export class YourModule {}
2. 简化监听器的注入写法
如果NotificationsService本身是用@Injectable()装饰的类,不需要额外加@Inject()装饰器,直接用类型注入即可:
@Injectable() export class ClientUpdatedListener { private readonly logger = new Logger(ClientUpdatedListener.name); // 移除多余的@Inject装饰器,直接通过类型注入 constructor(private notificationService: NotificationsService) {} @OnEvent(eventType.CLIENT_UPDATED) handleClientUpdatedEvent(event: ClientUpdatedEvent) { this.logger.log('Processing event: ' + eventType.CLIENT_UPDATED ); console.log(event); this.notificationService.emailClient(event.id); } }
3. 排查启动日志确认错误
如果调整后依然有问题,把NestJS的日志级别调整为debug,启动应用时查看是否有依赖解析错误:
- 常见错误包括
Nest can't resolve dependencies of the XxxService,对应补全对应的provider注册即可 - 不要将
ClientUpdatedListener设置为请求作用域/租户作用域,事件监听器需要为默认单例作用域才能正常注册全局事件监听
内容的提问来源于stack exchange,提问作者Eden WebStudio
相关产品推荐
相关产品推荐

