[英]Angular Circular dependency when inject TranslateService to interceptor
我在將依賴項注入攔截器時遇到問題。 我想將 TranslateService 注入 HttpErrorInterceptor,但出現循環依賴錯誤。 當我刪除 TranslateService 注入時,一切正常。
我已經在我的 app.module.ts 中聲明了攔截器。 我的應用模塊如下所示:
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
CoreModule,
HttpClientModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient],
},
defaultLanguage: 'pl-pl'
}),
AppRoutingModule,
RouterModule,
FormsModule,
ReactiveFormsModule,
ToastrModule.forRoot()
],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: JwtInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: HttpErrorInterceptor,
multi: true,
deps: [TranslateService, ToastrService]
}
],
bootstrap: [AppComponent]
})
export class AppModule { }
在 AppModule 中,我導入了 CoreModule,其中有一個包含攔截器的文件夾,我的 CoreModule 如下所示:
@NgModule({
declarations: [],
imports: [
CommonModule
],
providers: [
CookieService,
NoAuthGuard,
AuthGuard
]
})
export class CoreModule { }
我把登錄頁面放在AuthModule中,如下所示:
@NgModule({
declarations: [LoginComponent, AuthComponent, ForgotPasswordComponent],
imports: [
CommonModule,
AuthRoutingModule,
RouterModule,
SharedModule
],
providers: [
AuthService
]
})
export class AuthModule { }
在 Authmodule 中,我導入了 SharedModule,並在其中導出了 TranslateModule。 SharedModule 看起來像這樣:
@NgModule({
declarations: [],
imports: [
CommonModule,
HttpClientModule,
ReactiveFormsModule
],
exports: [
TranslateModule,
ReactiveFormsModule
]
})
export class SharedModule { }
我找不到登錄頁面上出現循環依賴錯誤的原因。
我的假設是我已經將 CoreModule 導入到 AppModule 中,在那里我保留了攔截器、守衛和 SharedModule,它對所有功能模塊進行了即興創作,並且我想在那里保留例如公共組件。
Błąd, jaki dostaję to:
core.js:6162 ERROR Error: NG0200: Circular dependency in DI detected for InjectionToken HTTP_INTERCEPTORS. Find more at https://angular.io/errors/NG0200
at throwCyclicDependencyError (core.js:216)
at R3Injector.hydrate (core.js:11381)
at R3Injector.get (core.js:11205)
at HttpInterceptingHandler.handle (http.js:1978)
at MergeMapSubscriber.project (http.js:1114)
at MergeMapSubscriber._tryNext (mergeMap.js:44)
at MergeMapSubscriber._next (mergeMap.js:34)
at MergeMapSubscriber.next (Subscriber.js:49)
at Observable._subscribe (subscribeToArray.js:3)
at Observable._trySubscribe (Observable.js:42)
您遇到的問題是,對於TranslateModule
的初始化,您依賴於HttpClient
,這意味着需要首先初始化HttpClientModule
。 這會導致您的HttpErrorInterceptor
初始化,因為攔截器是使用HttpClientModule
初始化進行初始化的。 這會導致循環依賴,因為您的攔截器需要TranslateService
。 您可以通過在HttpErrorInterceptor
中注入Injector來解決此問題,然后在需要時直接從注入器請求TranslateService
。 這樣可以防止對初始初始化的循環依賴。
由於您沒有為您的攔截器提供代碼,因此這里有一個使用此方法的示例攔截器。
@Injectable()
export class HttpErrorInterceptor implements HttpInterceptor {
constructor(private readonly injector: Injector) {}
public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
try {
const translateService = this.injector.get(TranslateService)
// log using translate service
} catch {
// log without translation translation service is not yet available
}
}
}
您仍然需要處理獲取翻譯服務失敗的情況,因為加載翻譯時可能會出錯。
根據這個GitHub 問題,包括我自己在內的一些人能夠通過刪除TranslateModule.forRoot()
中的defaultLanguage
來解決該問題
我已經實現了我的 LanguageModule 如下:
@NgModule({
imports: [
HttpClientModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: (createTranslateLoader),
deps: [HttpClient]
},
isolate: true
})
],
providers: [
TranslateService
]
})
export class LanguageModule {
public constructor(translateSvc: TranslateService, http: HttpClient) {
translateSvc.onLangChange
.pipe(
switchMap((currentLang: LangChangeEvent) => zip(
of(currentLang),
http.get(`path/to/i18n/${currentLang.lang}.json`)
))
).subscribe(([currentLang, localizations]) => {
translateSvc.setTranslation(translateSvc.currentLang, localizations, true);
});
translateSvc.use(translateSvc.getDefaultLang());
}
然后將其導入我的CoreModule
:
@NgModule({
imports: [
CommonModule,
HttpClientModule,
BrowserAnimationsModule,
LanguageModule,
...
],
exports: [],
declarations: [],
providers: [
...
{
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
multi: true
}
]
})
export class CoreModule {
public constructor(@Optional() @SkipSelf() parentModule: CoreModule, private translateSvc: TranslateService) {
this.translateSvc.use(environment.defaultLang)
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.