Angular 6+: при условии, что некорневой модуль вызывает циклическую зависимость
Я пытаюсь предоставить услугу разрешения через новый providedIn
атрибут.
Это преобразователь переводов, который я использую в защищенном модуле:
import { Injectable } from '@angular/core';
import { Observable , pipe } from 'rxjs';
import {map} from "rxjs/operators";
//This is causing: "WARNING in Circular dependency detected:"
import {ProtectedModule} from "../../../protected/protected.module";
import { HttpHandlerService } from '../../http/http-handler.service';
@Injectable({
providedIn: ProtectedModule //Over here (I need the import for this line)
})
export class TranslationsResolverService {
constructor(private _httpHandlerService : HttpHandlerService) { }
resolve(): any {
//Do Something...
}
}
Ответы
Ответ 1
Это не проблема угловых зависимостей.
Циклическая ссылка генерируется компилятором TypeScript при попытке разрешить циклический импорт.
Первое решение
Создайте новый модуль с именем ProtectedResolversModule
и используйте providedIn: ProtectedResolversModule
и переместите там резольверы.
Теперь вы можете импортировать этот модуль в ProtectedModule
и при загрузке ProtectedRoutingModule
вы не получите ошибку круговой зависимости.
Второе решение
Используйте массив providers
ProtectedModule
.
Ответ 2
Я столкнулся с той же проблемой. Оказывается, решение "не делай этого", как объяснил в этой теме один из парней из Angular: https://github.com/angular/angular-cli/issues/10170#issuecomment-380673276
Это сводится к тому, что сервисам легче встряхнуть дерево, когда они предоставляются корневым модулем, насколько я понимаю.
Я так же разочарован, как и вы.
Ответ 3
Я думаю, что Angular немного напутал в синтаксисе providedIn
. Кажется, это смутило многих людей. Например. увидеть эти две темы GitHub:
Синтаксис providedIn
, похоже, имеет 2 основных преимущества:
- Поддерживается тряска деревьев неиспользуемых сервисов
providedIn: 'root'
гарантирует, что вы получите только один экземпляр службы
Но вам действительно нужно (1), если вы пишете библиотеку, а не приложение (потому что зачем вам включать в приложение службу, которая вам не нужна), и вы можете избежать нескольких экземпляров службы (2) просто убедитесь, что вы не импортировали сервисный модуль более одного раза.
Проблемы с синтаксисом providedIn
:
providedIn: 'root'
разрывает связь между службой и модулем, в котором он "живет" (или "с") - потому что служба не знает о модуле, а модуль не знает о службе. Это означает, что сервис больше не "принадлежит" этому модулю и будет просто связан с тем, что на него ссылается. Это, в свою очередь, означает, что теперь потребитель сервиса должен убедиться, что инъекционные зависимости сервиса (если они есть) доступны до его использования, что вводит в заблуждение и довольно нелогично.
- Задача циклической ссылки описана выше. На самом деле невозможно - с помощью этого синтаксиса - сохранить связь между службой и ее модулем, если служба фактически используется какими-либо компонентами в том же модуле.
Это противоречит официальному руководству Angular, но мой совет: Не используйте providedIn
, если только вы не пишете стороннюю библиотеку, которая требует встряхивания деревьев - используйте старую (не рекомендуется) providers
вместо этого синтаксис в модуле, а именно:
@NgModule({
providers: [MyService],
})
Добавление
Я получил 5 голосов "за" за этот ответ, поэтому я чувствую, что должен прийти в себя и сказать, что больше не следую собственному совету по этому поводу!
Поскольку официальная (и широко используемая) политика Angular заключается в использовании providedIn: 'root'
, я решил, что в целом для других разработчиков было бы меньше путаницы, если бы я просто придерживался этого. До сих пор это не вызывало у меня никаких проблем, но вышеизложенные предостережения все еще остаются, и я считаю важным постоянно помнить об этом.
Ответ 4
Проверьте функцию forwardRef() из углового/ядро. Это позволяет ссылаться на ссылки, которые еще не определены.
import {MyService} from './service';
constructor(@Inject(forwardRef(() => MyService)) public myService: MyService) {
}