循环依赖如何解决
Nest 实现了一套模块系统,可以通过 imports 引用其他模块。
如果 Module 和 Module 互相引用,形成循环依赖怎么办?
现在我们创建两个 module:
bash1nest g module aaa 2nest g module bbb
然后让两个 module 互相引用:
ts1import { Module } from '@nestjs/common' 2import { BbbModule } from 'src/bbb/bbb.module' 3 4@Module({ 5 imports: [BbbModule], 6}) 7export class AaaModule {}
ts1import { Module } from '@nestjs/common' 2import { AaaModule } from 'src/aaa/aaa.module' 3 4@Module({ 5 imports: [AaaModule], 6}) 7export class BbbModule {}
执行pnpm run start:dev,nest 会直接报错:

由于 nest 启动时会递归 BbbModule 的依赖(AaaModule),而 AaaModule 又依赖了 BbbModule,造成了循环依赖,所以没办法创建成功,拿到的就是 undefined。
nest 的解决的方法是单独创建这两个依赖,然后让它们关联起来。
根据提示,我们需要使用 forwardRef。
ts1@Module({ 2 imports: [forwardRef(() => BbbModule)], 3})
ts1@Module({ 2 imports: [forwardRef(() => AaaModule)], 3})
nest 会单独创建两个 Module,之后再把 Module 的引用转发过去,也就是 forwardRef 的含义。
除了 Module 之间会有循环依赖之外,provider 也会有循环依赖的问题。
创建两个 service:
bash1nest g service ccc 2nest g service ddd
然后互相引用:
ts1@Injectable() 2export class CccService { 3 constructor(private readonly dddService: DddService) {} 4 ccc: () => 'ccc' 5}
ts1@Injectable() 2export class DddService { 3 constructor(private readonly cccService: CccService) {} 4 ddd: () => 'ddd' 5}
同样会报错:

然后用 forwardRef 单独创建依赖:
ts1@Injectable() 2export class CccService { 3 @Inject(forwardRef(() => DddService)) 4 private readonly dddService: DddService 5 ccc: () => 'ccc' 6}
ts1@Injectable() 2export class DddService { 3 @Inject(forwardRef(() => CccService)) 4 private readonly cccService 5 ddd: () => 'ddd' 6}
报错消失了:

总结
Module 之间可以相互 imports,Provider 之间可以相互注入,这两者都会形成循环依赖。
解决方式就是两边都用 forwardRef 来包裹下。
它的原理就是 nest 会先创建 Module、Provider,之后再把引用转发到对方,也就是 forward ref。