Nest.js 循环依赖

当两个类相互依赖时,就会发生循环依赖。 例如,A 类需要 B 类,B 类也需要 A 类。在 Nest 中,模块之间和提供者之间可能会出现循环依赖关系。

虽然应尽可能避免循环依赖,但您不能总是这样做。 在这种情况下,Nest 可以通过两种方式解决提供者之间的循环依赖关系。 在本章中,我们描述了使用前向引用作为一种技术,以及使用 ModuleRef 类从 DI 容器中检索提供者实例作为另一种技术。

我们还描述了解决模块之间的循环依赖关系。

警告 : 循环依赖也可以使用封装桶文件/index.ts文件成组导入。桶(Barrel)文件应该从模块/类中省略掉。例如,当在同一个目录下作为桶文件导入时不应使用桶文件,例如,cats/cats.controller不应该导入cat到cats/cats.service文件。更多内容参见github issue

前向引用

前向引用允许 Nest 引用目前尚未被定义的引用。当 CatsService 和 CommonService 相互依赖时,关系的双方都需要使用 @Inject()forwardRef() ,否则 Nest 不会实例化它们,因为所有基本元数据都不可用。让我们看看下面的代码片段:

cats.service.ts

@Injectable()
export class CatsService {
  constructor(
    @Inject(forwardRef(() => CommonService))
    private commonService: CommonService,
  ) {}
}

提示 : forwardRef() 函数是从 @nestjs/common 包中导入的。

这涵盖了关系的一方面。 现在让我们对 CommonService 做同样的事情:

common.service.ts

@Injectable()
export class CommonService {
  constructor(
    @Inject(forwardRef(() => CatsService))
    private catsService: CatsService,
  ) {}
}

警告 : 实例化的顺序是不确定的。 确保我们的代码不依赖于首先调用哪个构造函数。 具有循环依赖关系依赖于具有 Scope.REQUEST 的提供程序可能会导致未定义的依赖关系。

可选的模块引用(ModuleRef)类

一个选择是使用forwardRef()来重构你的代码,并使用ModuleRef类来在循环引用关系一侧获取提供者。

模块前向引用

为了解决模块之间的循环依赖关系,需要在模块关联的两侧使用相同的 forwardRef() 实用程序函数。 例如:

common.module.ts

@Module({
  imports: [forwardRef(() => CatsModule)],
})
export class CommonModule {}

查看笔记

扫码一下
查看教程更方便