NestJS中仅在AppModule导入模块,其他模块能否使用其导出内容?
我正在学习NestJS,查阅文档后仍未解决以下问题:
我的模块定义
InfrastructureModule
@Module({ imports: [DatabaseModule], controllers: [], providers: [ ConfigService, { provide: 'RequestClient', useClass: AxiosRequestClient }, { provide: 'FileStorage', useClass: S3FileStorage } ], exports: ['RequestClient', 'FileStorage', DatabaseModule] }) export class InfrastructureModule {}
AppModule
@Module({ imports: [ ConfigModule.forRoot({ load: [filesystemConfig, awsConfig, databaseConfig], isGlobal: true, cache: true }), InfrastructureModule, PhysicianModule, PatientModule, RemsModule ], controllers: [], providers: [ApiResponseInterceptor] }) export class AppModule {}
疑问与问题
我想知道:InfrastructureModule的导出内容是否能被PatientModule直接使用?还是必须要将InfrastructureModule手动导入到PatientModule中?
目前我尝试在PatientMedicalRecordFileRepository中注入依赖时:
export default class PatientMedicalRecordFileRepository implements IPatientMedicalRecordFileRepository { private readonly tempPath: string private readonly s3Path: string = 'private/patients' private readonly cloudfrontBaseUrl: string constructor( private readonly configService: ConfigService, @Inject('FileStorage') private readonly fileStorage: IFileStorageService ) { // 构造函数逻辑 } }
出现了如下错误:
ERROR [ExceptionHandler] Nest can't resolve dependencies of the PatientMedicalRecordFileRepository (ConfigService, ?). Please make sure that the argument FileStorage at index [1] is available in the RemsModule context.
问题解答
模块作用域规则
NestJS的模块具有隔离作用域,只有当模块被直接导入到目标模块时,它的导出内容才能在该目标模块的上下文中可用。你仅在AppModule中导入了InfrastructureModule,这意味着它的导出内容只能在AppModule内部使用,PatientModule、RemsModule等子模块无法直接访问这些导出的提供者。错误根源
从错误信息可以看出,PatientMedicalRecordFileRepository实际是在RemsModule的上下文里被实例化的,而RemsModule并没有导入InfrastructureModule,所以Nest无法找到FileStorage这个依赖提供者。解决方案
- 全局模块方案:如果希望
FileStorage等提供者能被所有模块复用,给InfrastructureModule添加@Global()装饰器,这样只需在AppModule中导入一次,所有其他模块都能直接使用它的导出内容:@Global() @Module({ imports: [DatabaseModule], providers: [ ConfigService, { provide: 'RequestClient', useClass: AxiosRequestClient }, { provide: 'FileStorage', useClass: S3FileStorage } ], exports: ['RequestClient', 'FileStorage', DatabaseModule] }) export class InfrastructureModule {} - 显式导入方案:在需要使用这些提供者的模块(比如PatientModule、RemsModule)中,显式导入InfrastructureModule,确保每个模块都能访问到所需的依赖。
内容的提问来源于stack exchange,提问作者z0mbieKale

