Circular Dependency
The circular dependency means that class A needs class B, and class B needs class A. Nest permits to create circular dependencies between both components and modules, but we advise you not to use it too much. Sometimes it's really difficult to avoid these types of the relationships, that's why we provided some ways to deal with this issue.
Forward reference
The forward reference allows Nest refer to references which are not yet defined.
When CatsService and CommonService depend on each other, both sides of the relationship need to use @Inject() and the forwardRef() utility, otherwise Nest won't create your components instances because all of the essential metadata would be not available.
Let's see the following snippet:
@Component()
export class CatsService {
constructor(
@Inject(forwardRef(() => CommonService))
private readonly commonService: CommonService,
) {}
}
@Component()
@Dependencies(forwardRef(() => CommonService))
export class CatsService {
constructor(commonService) {
this.commonService = commonService;
}
}
Notice TheforwardRef()function is imported from the@nestjs/commonpackage.
Here's the first side of the relationship. Now let's do the same with the CommonService:
@Component()
export class CommonService {
constructor(
@Inject(forwardRef(() => CatsService))
private readonly catsService: CatsService,
) {}
}
@Component()
@Dependencies(forwardRef(() => CatsService))
export class CommonService {
constructor(catsService) {
this.catsService = catsService;
}
}
Hint You never know which constructor will be called first.
To create circular dependencies between modules you have to use the same forwardRef() utility on the both parts of the modules association:
@Module({
imports: [forwardRef(() => CatsModule)],
})
export class CommonModule {}
Module reference
Nest provides the ModuleRef class, which might be simply injected into each component.
@Component()
export class CatsService implements OnModuleInit {
private service: Service;
constructor(private readonly moduleRef: ModuleRef) {}
onModuleInit() {
this.service = this.moduleRef.get<Service>(Service);
}
}
@Component()
@Dependencies(ModuleRef)
export class CatsService {
constructor(moduleRef) {
this.moduleRef = moduleRef;
}
onModuleInit() {
this.service = this.moduleRef.get(Service);
}
}
Notice TheModuleRefclass is imported from the@nestjs/corepackage.
The module reference has a get() method, which allows to retrieve any component available in the current module.