繁体   English   中英

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

[英]NestJS: Using forRoot / forChild in custom module - race condition?

此处提供了Repo来突出显示该问题。

我的比赛条件有问题。 我创建了一个ConfigModule它有一个forRoot和一个forChild

forRoot树立的加载.env文件和forChild使用它在另一个模块中。

问题是forChildforRoot之前被调用。 因为没有先执行forRoot所以ConfigService会注入缺少的配置。

> 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

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

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

因此,基本上, forChildforRoot之前执行并返回其自己的ConfigService

为了使其正常工作,如果您在AppModule注释掉InstanceModule ,则它将自动开始侦听并从环境变量返回端口号。

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

为什么这不起作用?

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

2)创建动态模块时,每个模块将是其自己的实例,它们不会像常规模块那样是单例。 对于您的情况,您将创建两个不同的ConfigModule实例,并使用它创建两个不同的ConfigService实例。 因此,他们不会共享您的.env配置。 独立于实例化顺序,这是行不通的。


备择方案

看一下nestjs/typeorm包。 它在TypeOrmCoreModule创建了一个共享的TypeOrmCoreModule ,该类型在TypeOrmModule.forRoot / TypeOrmModule.forChild创建的不同动态模块实例之间共享。 为了使其同时共享和动态,必须将其设置为@Global 在您的情况下,由于在forChild导入中没有任何配置,因此您只需将整个ConfigModule全局化,然后忽略forChild()导入,因为ConfigService仍然可以全局使用。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM