Dépendance circulaire
Une dépendance circulaire se produit lorsque deux classes dépendent l'une de l'autre. Par exemple, la classe A a besoin de la classe B, et la classe B a également besoin de la classe A. Les dépendances circulaires peuvent apparaître dans Nest entre les modules et entre les fournisseurs.
Les dépendances circulaires doivent être évitées dans la mesure du possible, mais ce n'est pas toujours possible. Dans ce cas, Nest permet de résoudre les dépendances circulaires entre les fournisseurs de deux manières. Dans ce chapitre, nous décrivons l'utilisation de références avancées comme une technique, et l'utilisation de la classe ModuleRef pour récupérer une instance de fournisseur dans le conteneur DI comme une autre technique.
Nous décrivons également la résolution des dépendances circulaires entre les modules.
Attention Une dépendance circulaire peut également être causée par l'utilisation de "barrel files"/index.ts pour regrouper les importations. Les "barrel files" doivent être omis lorsqu'il s'agit de classes de modules/fournisseurs. Par exemple, les barrel files ne devraient pas être utilisés lors de l'importation de fichiers dans le même répertoire que le barrel file, c'est-à-dire quecats/cats.controller
ne devrait pas importercats
pour importer le fichiercats/cats.service
. Pour plus de détails, veuillez également consulter ce problème github.
Référence avancée#
Une référence avancée permet à Nest de référencer des classes qui ne sont pas encore définies en utilisant la fonction utilitaire forwardRef()
. Par exemple, si CatsService
et CommonService
dépendent l'un de l'autre, les deux parties de la relation peuvent utiliser @Inject()
et l'utilitaire forwardRef()
pour résoudre la dépendance circulaire. Sinon Nest ne les instanciera pas car toutes les métadonnées essentielles ne seront pas disponibles. Voici un exemple :
@Injectable()
export class CatsService {
constructor(
@Inject(forwardRef(() => CommonService))
private commonService: CommonService,
) {}
}
@Injectable()
@Dependencies(forwardRef(() => CommonService))
export class CatsService {
constructor(commonService) {
this.commonService = commonService;
}
}
Astuce La fonctionforwardRef()
est importée du paquet@nestjs/common
.
Cela couvre un côté de la relation. Faisons maintenant la même chose avec CommonService
:
@Injectable()
export class CommonService {
constructor(
@Inject(forwardRef(() => CatsService))
private catsService: CatsService,
) {}
}
@Injectable()
@Dependencies(forwardRef(() => CatsService))
export class CommonService {
constructor(catsService) {
this.catsService = catsService;
}
}
Attention L'ordre d'instanciation est indéterminé. Assurez-vous que votre code ne dépend pas du constructeur appelé en premier. Avoir des dépendances circulaires qui dépendent de providers avec Scope.REQUEST
peut conduire à des dépendances non définies. Plus d'informations disponibles ici
Alternative de la classe ModuleRef#
Une alternative à l'utilisation de forwardRef()
est de remanier votre code et d'utiliser la classe ModuleRef
pour récupérer un fournisseur d'un côté de la relation (autrement) circulaire. Pour en savoir plus sur la classe utilitaire ModuleRef
, cliquez ici.
Référence avancée de module#
Afin de résoudre les dépendances circulaires entre les modules, utilisez la même fonction utilitaire forwardRef()
des deux côtés de l'association des modules. Par exemple :
@Module({
imports: [forwardRef(() => CatsModule)],
})
export class CommonModule {}
Cela couvre un aspect de la relation. Faisons maintenant la même chose avec CatsModule
:
@Module({
imports: [forwardRef(() => CommonModule)],
})
export class CatsModule {}