首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >向拦截器注入TranslateService时的角度循环依赖关系

向拦截器注入TranslateService时的角度循环依赖关系
EN

Stack Overflow用户
提问于 2021-04-19 02:51:52
回答 2查看 898关注 0票数 3

我在向拦截器注入依赖项时遇到了问题。我想把TranslateService注入到HttpErrorInterceptor中,但是我得到了一个循环依赖错误。当我移除TranslateService注入时,一切都正常了。

我在我的app.module.ts中声明了拦截器。我的应用程序模块如下所示:

代码语言:javascript
运行
复制
@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如下所示:

代码语言:javascript
运行
复制
@NgModule({
  declarations: [],
  imports: [
    CommonModule
  ],
  providers: [
    CookieService,
    NoAuthGuard,
    AuthGuard
  ]
})
export class CoreModule { }

我将登录页面放在AuthModule中,如下所示:

代码语言:javascript
运行
复制
@NgModule({
  declarations: [LoginComponent, AuthComponent, ForgotPasswordComponent],
  imports: [
    CommonModule,
    AuthRoutingModule,
    RouterModule,
    SharedModule
  ],
  providers: [
    AuthService
  ]
})
export class AuthModule { }

在Authmodule中,我导入了SharedModule,并在其中导出了TranslateModule。和SharedModule看起来像这样:

代码语言:javascript
运行
复制
@NgModule({
  declarations: [],
  imports: [
    CommonModule,
    HttpClientModule,
    ReactiveFormsModule
  ],
  exports: [
    TranslateModule,
    ReactiveFormsModule
  ]
})
export class SharedModule { }

我找不到为什么我在登录页面上有一个循环依赖错误。

我的假设是,我已经将CoreModule导入到AppModule中,在那里我保留了拦截器和守卫,并且我有SharedModule,它可以即兴使用所有功能模块,我希望将公共组件保留在那里。

Błąd,jaki dostajęto:

代码语言:javascript
运行
复制
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)
EN

回答 2

Stack Overflow用户

发布于 2021-04-19 05:30:30

您遇到的问题是,对于TranslateModule的初始化,您依赖于HttpClient,这意味着需要首先初始化HttpClientModule。这会导致初始化您的HttpErrorInterceptor,因为拦截器是使用HttpClientModule初始化进行初始化的。这会导致循环依赖,因为您的拦截器需要TranslateService。您可以通过在HttpErrorInterceptor中注入Injector来解决此问题,然后在需要时直接从注入器请求TranslateService。这样,您就可以防止对初始初始化的循环依赖。

由于您没有为您的拦截器提供代码,因此这里有一个使用此方法的示例拦截器。

代码语言:javascript
运行
复制
@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
    }
  }
}

您仍然需要处理获取翻译服务失败的情况,因为您可能会在加载翻译时出错。

票数 4
EN

Stack Overflow用户

发布于 2021-09-29 09:47:28

根据this GitHub issue的说法,一些人-包括我自己-能够通过删除TranslateModule.forRoot()中的defaultLanguage来解决该问题

我按如下方式实现了我的LanguageModule:

代码语言:javascript
运行
复制
@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

代码语言:javascript
运行
复制
@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)
    }
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67152273

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档