Circular dependency

A circular dependency occurs when two classes depend on each other. For example, class A needs class B, and class B also needs class A. Circular dependencies can arise in Nest between modules and between providers. While circular dependencies should be avoided where possible, you can’t always do so. Nest enables resolving circular dependencies using a technique called forward referencing.

Forward reference

A forward reference allows Nest to reference classes which aren’t yet defined using the forwardRef() utility function. For example, if CatsService and CommonService depend on each other, both sides of the relationship can use @Inject() and the forwardRef() utility to resolve the circular dependency. Otherwise Nest won’t instantiate them because all of the essential metadata won’t be available. Here’s an example:

  1. @@filename(cats.service)
  2. @Injectable()
  3. export class CatsService {
  4. constructor(
  5. @Inject(forwardRef(() => CommonService))
  6. private readonly commonService: CommonService,
  7. ) {}
  8. }
  9. @@switch
  10. @Injectable()
  11. @Dependencies(forwardRef(() => CommonService))
  12. export class CatsService {
  13. constructor(commonService) {
  14. this.commonService = commonService;
  15. }
  16. }

info Hint The forwardRef() function is imported from the @nestjs/common package.

That covers one side of the relationship. Now let’s do the same with CommonService:

  1. @@filename(common.service)
  2. @Injectable()
  3. export class CommonService {
  4. constructor(
  5. @Inject(forwardRef(() => CatsService))
  6. private readonly catsService: CatsService,
  7. ) {}
  8. }
  9. @@switch
  10. @Injectable()
  11. @Dependencies(forwardRef(() => CatsService))
  12. export class CommonService {
  13. constructor(catsService) {
  14. this.catsService = catsService;
  15. }
  16. }

warning Warning The order of instantiation is indeterminate. Make sure your code does not depend on which constructor is called first.

Module forward reference

In order to resolve circular dependencies between modules, use the same forwardRef() utility on both sides of the modules association. For example:

  1. @@filename(common.module)
  2. @Module({
  3. imports: [forwardRef(() => CatsModule)],
  4. })
  5. export class CommonModule {}

Module reference

Nest provides the ModuleRef class to navigate the internal list of providers and obtain a reference to any provider by class name. ModuleRef can be injected into a class in the normal way:

  1. @@filename(cats.service)
  2. @Injectable()
  3. export class CatsService implements OnModuleInit {
  4. private service: Service;
  5. constructor(private readonly moduleRef: ModuleRef) {}
  6. onModuleInit() {
  7. this.service = this.moduleRef.get(Service);
  8. }
  9. }
  10. @@switch
  11. @Injectable()
  12. @Dependencies(ModuleRef)
  13. export class CatsService {
  14. constructor(moduleRef) {
  15. this.moduleRef = moduleRef;
  16. }
  17. onModuleInit() {
  18. this.service = this.moduleRef.get(Service);
  19. }
  20. }

info Hint The ModuleRef class is imported from the @nestjs/core package.

The module reference has a get() method which retrieves a provider available in the current module by class name. To retrieve a provider from the global context (anywhere in the application), pass the {{ '{' }} strict: false {{ '}' }} option as a second argument to get().

  1. this.moduleRef.get(Service, { strict: false });