【发布时间】:2021-06-26 10:31:54
【问题描述】:
我一直在努力寻找处理导入在同一范围内具有相互依赖关系的 Nest 模块的最佳方法。
我的具体用例是一个大型 monorepo,其中包含多个微服务应用程序,这些应用程序需要一组通用组件(例如数据库、传输等)的特定配置/设置。我的目的是提供一个“汇总”模块来标准化配置过程。
问题在于模块导入数组中的模块似乎完全相互隔离。虽然我可以使用@Global,但它违背了模块级隔离的目的,坦率地说有点@Dirty。
我尝试过的简化版本:
@Module({})
export class ChaptersModule {
static registerAsync(config: IChaptersAsyncConfig): DynamicModule {
const provider = {
provide: CHAPTERS,
useFactory: config.useFactory,
inject: config.inject || [],
};
return {
module: ChaptersModule,
imports: [CharactersModule], // <-- another DynamicModule
providers: [provider, ChaptersService],
exports: [ChaptersService],
};
}
}
将该模块及其依赖项导入另一个模块时:
@Module({
imports: [
CharactersModule.forRootAsync({
useFactory: () => characterData,
}),
ChaptersModule.registerAsync({
useFactory: () => chapterData,
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Nest 实例化 CharactersModule 两次(一次用于顶级导入,一次用于 ChaptersModule 导入),即使 它们共享相同的消费模块范围。因为模块需要配置,Nest 实例化时没有它的配置提供程序,我得到了我最好的新朋友:
Error: Nest can't resolve dependencies of the ChaptersService (CHAPTERS, ?). Please make sure that the argument CharactersService at index [1] is available in the ChaptersModule context.
在这件事上花费的时间比我愿意公开分享的要多,我能找到的唯一解决方法是实例化 CharactersModule 并然后通过 requires?: any[] 属性将其传递给依赖模块添加到我的界面。
// Pre-Configure any dependent modules
export const configured = [
CharactersModule.forRoot(characterData)
]
@Module({
imports: [
...configured, // include configured modules in module imports
ChaptersModule.registerAsync({
requires: configured, // pass configured modules
useFactory: () => chapterData
})
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
这感觉很hacky并且似乎有效,但我肯定错过了什么吗?示例 repo 是 here(我预计它的工作方式是在 broken 分支中。
处理场景的正确方法是什么?
【问题讨论】:
标签: nestjs