Круговая зависимость возникает, когда два класса зависят друг от друга. Например, класс A нуждается в классе B, а класс B также нуждается в классе A. Циркулярные зависимости могут возникать в Nest между модулями и между провайдерами.
Хотя круговых зависимостей следует избегать по возможности, это не всегда возможно. В таких случаях Nest позволяет разрешать круговые зависимости между провайдерами двумя способами. В этой главе мы опишем использование прямой ссылки как один из способов, и использование класса ModuleRef для получения экземпляра провайдера из DI-контейнера как другой.
Мы также опишем разрешение круговых зависимостей между модулями.
При использовании файлов "barrel files (не понял как это перевести)"/index.ts для группировки импорта также может возникнуть круговая зависимость. Файлы barrel следует опускать, когда речь идет о классах модулей/провайдеров. Например, файлы barrel не должны использоваться при импорте файлов в том же каталоге, что и файл barrel, т.е.
cats/cats.controller
не должен импортироватьcats
для импорта файлаcats/cats.service
.
Прямая ссылка
Прямая ссылка позволяет Nest ссылаться на классы, которые еще не определены, используя функцию утилиты forwardRef()
. Например, если CatsService
и CommonService
зависят друг от друга, обе стороны отношений могут использовать @Inject()
и утилиту forwardRef()
для разрешения круговой зависимости. В противном случае Nest не будет инстанцировать их, потому что все необходимые метаданные будут недоступны. Вот пример:
cats.service.ts
@Injectable()
export class CatsService {
constructor(
@Inject(forwardRef(() => CommonService))
private commonService: CommonService,
) {}
}
Функция
forwardRef()
импортируется из пакета@nestjs/common
.
Это охватывает одну сторону отношений. Теперь давайте сделаем то же самое с CommonService
:
@Injectable()
export class CommonService {
constructor(
@Inject(forwardRef(() => CatsService))
private catsService: CatsService,
) {}
}
Порядок инстанцирования неопределен. Убедитесь, что ваш код не зависит от того, какой конструктор вызывается первым.
Альтернатива классу ModuleRef
Альтернативой использованию forwardRef()
является рефакторинг вашего кода и использование класса ModuleRef
для получения провайдера с одной стороны круговой связи.
Прямая ссылка на модуль
Чтобы разрешить круговые зависимости между модулями, используйте одну и ту же служебную функцию forwardRef()
в обоих взаимозависимых модулях. Например:
common.module.ts
@Module({
imports: [forwardRef(() => CatsModule)],
})
export class CommonModule {}
0 комментариев