NestJS中Event Emitter监听函数被调用两次的问题排查
问题原因解析
第一种配置出现两次日志的核心原因是创建了两个EmitterService实例,且它们都向同一个EventEmitter2注册了事件监听器。
具体分析:
第一种配置(TestModule直接声明EmitterService为provider)
- 假设你的应用根模块(AppModule)已经导入了
EmitterModule,那么EmitterModule会创建一个EmitterService实例(记为实例A),并通过@OnEvent装饰器将listentToEvent方法注册到全局唯一的EventEmitter2实例上。 - 同时,
TestModule在自己的providers数组中声明了EmitterService,这会让NestJS为TestModule单独创建另一个EmitterService实例(记为实例B),该实例同样会把listentToEvent方法注册到同一个EventEmitter2上。 - 当你调用
testEventEmitter接口时,使用的是实例B的emitEvent方法,触发msg.sent事件后,EventEmitter2会通知所有已注册的监听器——也就是实例A和实例B的listentToEvent方法都会执行,因此日志会输出两次"second"。
- 假设你的应用根模块(AppModule)已经导入了
第二种配置(TestModule导入EmitterModule)
TestModule通过导入EmitterModule,共享了EmitterModule导出的EmitterService单例实例(只有实例A)。- 此时整个应用中只有一个
EmitterService实例,它的listentToEvent方法只会注册一次,因此事件触发后只会输出一次"second"。
总结:
NestJS中,若在多个模块的providers数组中重复声明同一个服务,会为每个模块创建独立的服务实例。而通过导入共享模块(如EmitterModule)的方式,才能保证服务是单例的,避免重复注册监听器这类问题。
内容的提问来源于stack exchange,提问作者Đoàn Đức Bảo
相关产品推荐
相关产品推荐

