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
方法中。
关于javascript - NestJS:在自定义模块中使用forRoot/forChild-竞赛条件?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55323943/