What is the correct way to import dynamic modules when there's a circular dependency between them? I simply changed forwardRef(() => MyModule)
to forwardRef(() => MyModule.forRoot())
, and I'm getting Nest can't resolve dependencies
error.
Avoiding circular dependencies by refactoring The NestJS documentation advises that circular dependencies be avoided where possible. Circular dependencies create tight couplings between the classes or modules involved, which means both classes or modules have to be recompiled every time either of them is changed.
To reduce or eliminate circular dependencies, architects must implement loose component coupling and isolate failures. One approach is to use abstraction to break the dependency chain. To do this, you introduce an abstracted service interface that delivers underlying functionality without direct component coupling.
In other words, dynamic modules provide an API for importing one module into another, and customizing the properties and behavior of that module when it is imported, as opposed to using the static bindings we've seen so far.
The best way to deal with nest module dependency is to import dependencies always through modules and never through services. If you run into a circular dependency, nest will show you an error and you can easily fix it with forwardRef().
let say your application has 3 tightly coupled modules.
And two supporting modules
Also, all modules are exporting services with the same name.
Consider a situation where
@moduleA() imports [serviceB, serviceX]
And
@moduleB() imports [serviceA, serviceY, serviceZ]
Now in @moduleC()
if you want to use serivceA() then you will have to
@moduleC() imports [serviceA, serviceB, serviceX, serviceY, serviceZ]
In most cases, nest throws the correct error saying which dependency is missing where. But some times, nest only says dependency at [index
] is missing, nest doesn't says where it is missing. This will lead to great level of confusion.
A neat approach is to always import modules
@moduleA() imports [moduleB, moduleX]
@moduleB() imports [moduleA, moduleY, moduleZ]
@moduleC() imports [moduleA]
If nest is complaining again about dependency issue then import modules using forwardRef
@module({
imports: [
forwardRef(() => ModuleA)
ModuleB
],
controllers: [],
providers: []
})
Sometimes even after doing all these, you may again run into dependency not available error. Then you can use ModuleRef
. Let's take the same example where you want to use ServiceA() in ModuleC()
You will then be adding serviceA() to providers[] in ModuleC() and in the serviceC() class you need to add the following.
import { Injectable, OnModuleInit } from '@nestjs/common'; \\need OnModuleInit
import { ServiceA} from '../FolderA/serviceA.service';
export class ServiceC implements OnModuleInit {
private serviceA: ServiceA;
constructor(private readonly moduleRef: ModuleRef) {}
onModuleInit() {
this.serviceA= this.moduleRef.get(ServiceA);
}
foo(){
console.log(this.serviceA.someFunction())
}
}
Please check more at Official documentation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With