javascript - NestJS: Özel modülde forRoot/forChild kullanımı - yarış durumu?
Sorunu vurgulamak için repo burada mevcut.
Bir yarış durumu ile ilgili bir sorun yaşıyorum. Bir ConfigModule oluşturdum - bunun bir forRoot ve bir forChild özelliği var.
forRoot, .env dosyasının yüklenmesini ayarlar ve forChild başka bir modülde bunu kullanır.
Sorun şu ki forChild, forRoot'den önce çağrılıyor. ConfigService, forRoot önce çalıştırılmadığı için eksik konfigürasyonla enjekte edilecektir.
> AppModule > ConfigModule.forRoot InstanceModule >
> ConfigModule.forChild
Bunu çıktı olarak veren bazı basit console.log komutları koydum
I am in Config Module FOR CHILD
I am in Config Module FOR ROOT
Gördüğünüz gibi, forChild önce çalıştırılıyor, forwardRef kullanmayı denedim ve işe yaramadı.
Uygulamanın çalışmasına izin verirseniz göreceksiniz
[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
Bunun nedeni, bazı process.env öğelerinin dotenv aracılığıyla yüklendiğini kontrol etmemdir. Elbette, forRoot önce çalıştırılmadığı için forChild kendi yeni ConfigService örneğini döndürür.
ConfigService, ortam değişkenlerinin kullanılabilirliğini doğrular.
Yani, temelde, forChild kendi ConfigService'ini forRoot'den önce çalıştırıyor ve döndürüyor.
Bunu çalıştırmak için, AppModule içindeki InstanceModule'ü yorum satırı haline getirirseniz, otomatik olarak dinlemeye başlar ve port numarasını bir ortam değişkeninden döndürür.
Elbette, çünkü InstanceModule forChild kullanıyor - bir yarış durumu var.
Cevap #1
Bu neden çalışmıyor?
1) Nest, bir bağımlılık grafiği oluşturur ve verilen modülleri ve sağlayıcılarını bu grafiğe göre başlatır. İçe aktarmalarınızın sırası veya dinamik modüllerinizin yöntemlerinin (forRoot/forChild) isimlendirilmesi başlatma sırasını etkilemez.
2) Dinamik modüller oluşturduğunuzda, her modül kendi örneği olacaktır, normal modüller gibi tekil (singleton) olmayacaktır. Sizin durumunuzda, iki farklı ConfigModule örneği oluşturacak ve bununla birlikte iki farklı ConfigService örneği elde edeceksiniz; bu yüzden .env yapılandırmanızı paylaşmayacaklardır. Bu, örnekleme sırasından bağımsız olarak çalışmaz.
Alternatifler
nestjs/typeorm paketine göz atın. Altında, farklı dinamik modül örnekleri arasında paylaşılan bir TypeOrmCoreModule oluşturur; bu örnekler TypeOrmModule.forRoot/TypeOrmModule.forChild tarafından yaratılır. Hem paylaşılan hem de dinamik olabilmesi için, @Global olarak işaretlenmesi gerekir. Sizin durumunuzda, forChild import’lerinizde herhangi bir konfigürasyon olmadığı için, tüm ConfigModule modülünü global yapabilir ve ardından forChild() import’lerini atlayabilirsiniz, çünkü ConfigService zaten global olarak erişilebilir olacaktır.
Hizmetinizin dünya çapında kullanılmasını istemiyorsanız, hizmetinizi başlatma işleminin ardından, örneğin AppModule’ünüzün onModuleInit yönteminde başlatabilirsiniz.