在NestJs中配置依赖DynamicModules的最佳方式



我一直在努力寻找最好的方法来处理导入同一范围内具有相互依赖性的Nest模块的问题。

我的具体用例是一个带有几个微服务应用程序的大型monoreo,这些应用程序需要一组通用组件(例如数据库、传输等(的特定配置/设置;"汇总";模块,以标准化配置过程。

问题是,模块导入数组中的模块似乎彼此完全隔离。虽然我可以使用@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 {}

这感觉很粗糙,似乎有效,但我肯定错过了什么?示例repo在这里(我预期它的工作方式是在broken分支中。

处理这种情况的正确方法是什么?

我有一个Git repo,它介绍了如何使用一些聪明的RxJS实现这一点,但我也会在这里给出一个高级概述。

因此,我们的想法是,您的模块类最终会有几个RxJS运算符和属性;即保持模块配置的Deferred静态变量、专用静态timeout变量和Subject变量。然后,在forRoot()forRootAsync()内部,在返回配置之前,您最终会调用this.moduleConfig.next(configuration)。现在,在应用程序中任何其他需要的地方,都可以调用Module.Deferred并获得RxJS延迟配置。此Deferred是位于timeoutsubject.pipe(take(1))之间的race,它将允许您在以后获得错误(从未调用过配置(或配置。

@golevelup/nestjs-modules有一个名为externallyConfigured()的方法,它几乎可以为您处理以上内容。我强烈建议给我链接的回购进行一次阅读,以了解模式,然后对我链接的一揽子计划进行一次注射,看看它能处理多少。

最新更新