注入registerAsync构建的服务失败:构造函数未执行,如何配置?
问题
我在一个模块中导入了另一个模块,但MyService的构造函数未被调用,怀疑是提供者配置错误。相关代码如下:
a.module.ts
@Global() @Module({ imports: [PassportModule, HttpModule], providers: [ { provide: ServiceConnector, useFactory: async ( options: ConfigModuleOptions, httpService: HttpService, currentRequest: Request ) => new ServiceConnector(options, httpService, currentRequest), inject: [MODULE_OPTIONS_TOKEN, HttpService, REQUEST], }, ], exports: [ ServiceConnector ], }) export class AModule extends ConfigurableModuleClass {}
b.module.ts
@Module({ imports: [ AModule.registerAsync({ useFactory: (configService: ConfigService) => { return { identity: configService.get('identity'), }; }, inject: [ConfigService], }) ], providers: [MyService], }) export class BModule {}
MyService.service.ts
@Injectable export class MyService { private _logger = new Logger(MyService.name); constructor( @Inject(ServiceConnector) private readonly connector: ServiceConnector, ) { console.log(this.connector); } ... }
请问我遗漏了什么?如何正确注入通过registerAsync构建的服务?
问题分析与解决办法
1. 修复@Injectable装饰器
MyService的@Injectable装饰器缺少括号,Nest无法识别该类为可注入的提供者,导致构造函数不会被触发。修改为:
@Injectable() // 补上括号 export class MyService { private _logger = new Logger(MyService.name); constructor( @Inject(ServiceConnector) private readonly connector: ServiceConnector, ) { console.log(this.connector); } ... }
2. 处理请求作用域的影响
ServiceConnector的工厂函数注入了REQUEST对象,这会将该服务标记为请求作用域。Nest中,单例作用域的服务注入请求作用域的服务时,自身会被自动提升为请求作用域,意味着MyService只有在有HTTP请求进入时才会被实例化,构造函数才会执行。
如果不需要请求上下文:
- 移除工厂函数中
REQUEST的注入,将ServiceConnector改为单例作用域,这样MyService会在应用启动时被实例化。
如果确实需要请求上下文:
- 发送一个HTTP请求到应用,此时
MyService会被创建,构造函数中的日志会输出。
3. 验证ConfigurableModuleClass配置
确保AModule继承的ConfigurableModuleClass是通过@nestjs/config的ConfigurableModuleBuilder正确生成的,保证MODULE_OPTIONS_TOKEN能正确获取到registerAsync传入的配置参数,避免因配置未正确注入导致ServiceConnector无法实例化。
内容的提问来源于stack exchange,提问作者Sancho
相关产品推荐
相关产品推荐

