angular - 无法在拦截器使用的服务内实例化循环依赖关系

标签 angular

我正在使用 Angular 10,并且有一些服务和一个拦截器导致:

ERROR Error: Uncaught (in promise): Error: Cannot instantiate cyclic dependency! InjectionToken HTTP_INTERCEPTORS Error: Cannot instantiate cyclic dependency! InjectionToken HTTP_INTERCEPTORS

app.module.ts

@NgModule({
  declarations: [
    AppComponent,
    DashboardComponent,
  ],
  imports: [
    AuthModule, // <= A custom module
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
  ],
  providers: [
    {provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true},
  ],
  bootstrap: [AppComponent]
})
export class AppModule {
}

拦截器

@Injectable()
export class ErrorInterceptor implements HttpInterceptor {

  constructor(
    private responseHandler: HttpResponseHandlerService
  ) {
  }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(request)
      .pipe(
        catchError((err: HttpErrorResponse, source) =>
          this.responseHandler.onCatch(err, source) // Catching all the errors here.
        )
      );
  }

}

HttpResponseHandlerService

@Injectable({
  providedIn: 'root',
})
export class HttpResponseHandlerService {

  constructor(
    // This is causing the error!
    private authService: AuthService
  ) {
  }

  public onCatch(response: HttpErrorResponse, source: Observable<any>): Observable<any> {
    return throwError(response);
  }

}

验证模块

@NgModule({
  declarations: [
    LoginComponent
  ],
  imports: [
    SharedModule, // <= A shared module
    AuthRoutingModule
  ],
  providers: [
    AuthService
  ]
})
export class AuthModule {
}

验证服务

@Injectable()
export class AuthService extends HttpService {

  constructor(
    // Maybe this is causing the cyclic dependency ?
    http: HttpClient
  ) {
    super(http);
  }

  login(username: string, password: string) {
  }

}

共享模块

@NgModule({
  declarations: [],
  imports: [
    CommonModule,
  ],
  exports: [
    FormsModule,
    ReactiveFormsModule,
  ],
  providers: [
    HttpService // <= A custom service to handle HTTP requests
  ]
})
export class SharedModule {
}

Http服务

@Injectable()
export class HttpService {

  constructor(
    private http: HttpClient
  ) {
  }

  get<T>(options: any): Observable<T> {
  }

}

我已经尝试了所有方法,但无法解决这个问题。我不明白错误的根源。

我的目标是正确解决循环依赖问题。

最佳答案

我猜测 HttpClient 会注入(inject) HTTP 拦截器。所以这一行:

    {provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true},

可能使得 Angular 需要先创建一个 ErrorInterceptor 实例,然后才能创建 HttpClient。

但是ErrorInterceptor注入(inject)了HttpResponseHandlerService,HttpResponseHandlerService又注入(inject)了AuthService,AuthService又注入(inject)了HttpClient。所以 Angular 就像:

new AuthService(
  new HttpClient([new ErrorInterceptor(
    new HttpResponseHandlerService(
      new AuthService(
         ... wait a minute.

解决此问题的最佳方法在一定程度上取决于这些不同服务之间依赖关系的性质。

希望如果您查看 HttpResponseHandlerService 计划使用 AuthService 做什么,您会发现您正在调用一个方法实际上并不需要HttpClient。如果是这种情况,也许您可​​以将该方法重构为一个单独的服务,该服务可以安全地注入(inject)到 HttpResponseHandlerService 中。

如果情况并非如此,您可能需要考虑其他模式,例如让 AuthService 从工厂或服务定位器按需获取 HttpClient,而不是直接注入(inject)它。

关于angular - 无法在拦截器使用的服务内实例化循环依赖关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64016059/

相关文章:

angular - MSAL、Angular 和 ASP.NET Core 的 CORS 错误

javascript - 使用 Angular (v4) AnimationBuilder 使宽度无响应

Angular 9 Uncaught ReferenceError : regeneratorRuntime is not defined

angular - loadchildren 在 Angular4 中不起作用?

Angular:区分参数和子路由

javascript - 尝试在用户更改页面语言时翻译 NgPickDateTime 标签

angular - Ng serve 在 Windows 中工作,但在 Ubuntu 中失败

css - Angular 5 - 链接到 node_module 文件夹中的 css 文件

javascript - 取消订阅上传可观察到的 Angular 6停止上传进度但不是实际上传

Angular 8 通用服务器端渲染