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
- 存在竞争条件。
1)Nest构建依赖图并根据该图实例化给定模块及其提供者。导入的顺序或动态模块方法的命名(forRoot
/ forChild
)不会影响实例化的顺序。
2)当你创建动态模块时,每个模块都是它自己的实例,它们不会像常规模块那样是单例。在您的情况下,您将创建两个不同的ConfigModule
实例,并使用它,两个不同的ConfigService
实例;因此他们不会分享您的.env
配置。这不起作用,与实例化顺序无关。
看看nestjs/typeorm
包。在引擎盖下,它创建了一个共享的TypeOrmCoreModule
,它由TypeOrmModule.forRoot
/ TypeOrmModule.forChild
创建的不同动态模块实例共享。为了让它在同一时间共享和动态,它必须成为@Global
。在你的情况下,由于你的forChild
进口中没有任何配置,你只需要整个ConfigModule
全局,然后省略forChild()
进口,因为ConfigService
无论如何都是全球可用的。
如果您不希望您的服务全局可用,则可以在启动过程后初始化您的服务,例如在AppModule
的onModuleInit
方法中。