NestJS:在自定义模块中使用forRoot / forChild - 竞争条件?

问题描述 投票:1回答:1

Repo可在此处突出显示该问题。

我遇到了种族问题。我创造了一个ConfigModule - 这有一个forRoot和一个forChild

forRoot设置了.env文件的加载,而forChild在另一个模块中使用它。

问题是在forChild之前调用forRoot。由于ConfigService没有先执行,所以forRoot会注入缺少的配置。

> AppModule > ConfigModule.forRoot InstanceModule >
> ConfigModule.forChild

我放置了一些简单的console.log命令输出

I am in Config Module  FOR CHILD
I am in Config Module  FOR ROOT

正如你可以看到forChild首先被执行,我尝试使用forwardRef,但是没有用。

如果您让应用程序运行,您将看到

[2019-03-24T11:49:33.602] [ERROR] ConfigService - There are missing mandatory configuration: Missing PORT
[2019-03-24T11:49:33.602] [FATAL] ConfigService - Missing mandatory configuration, cannot continue!, exiting

这是因为我检查了一些通过process.env加载的dotenv。当然,因为forRoot不是先执行然后forChild返回它自己的新ConfigService实例。

ConfigService验证环境变量的可用性。

所以,基本上,forChild正在执行并在ConfigService之前返回自己的forRoot

为了使它工作,如果你在InstanceModule中注释掉AppModule,那么它将自动开始监听并从环境变量返回端口号。

当然,因为InstanceModule使用forChild - 存在竞争条件。

javascript node.js typescript nestjs
1个回答
0
投票

为什么这不起作用?

1)Nest构建依赖图并根据该图实例化给定模块及其提供者。导入的顺序或动态模块方法的命名(forRoot / forChild)不会影响实例化的顺序。

2)当你创建动态模块时,每个模块都是它自己的实例,它们不会像常规模块那样是单例。在您的情况下,您将创建两个不同的ConfigModule实例,并使用它,两个不同的ConfigService实例;因此他们不会分享您的.env配置。这不起作用,与实例化顺序无关。


备择方案

看看nestjs/typeorm包。在引擎盖下,它创建了一个共享的TypeOrmCoreModule,它由TypeOrmModule.forRoot / TypeOrmModule.forChild创建的不同动态模块实例共享。为了让它在同一时间共享和动态,它必须成为@Global。在你的情况下,由于你的forChild进口中没有任何配置,你只需要整个ConfigModule全局,然后省略forChild()进口,因为ConfigService无论如何都是全球可用的。

如果您不希望您的服务全局可用,则可以在启动过程后初始化您的服务,例如在AppModuleonModuleInit方法中。

© www.soinside.com 2019 - 2024. All rights reserved.