HttpInterceptor-> Service-> HttpClient Cyclic Dependency

时间:2017-07-20 11:26:03

标签: angular

所以我有我的身份验证服务 AuthService ,基本上有两种方法,一种是从服务器获取新令牌,给定用户名和密码,另一种是检索当前存储的令牌必要时在过程中刷新令牌。 两者显然都依赖于 HttpClient 。也就是说, AuthService 依赖于 HttpClient 。让我们记住这一点。

另一项"服务"是 HttpInterceptor ,我想拦截除 AuthService 以外的所有传出请求以添加授权标题(它正在获取)现在很脏)。为了构成标题,我们需要一个令牌,我们可以从 AuthService 获得。也就是说, AuthInterceptor (我的拦截器的名称)依赖于 AuthService 。据我所知, HttpClient 依赖于所有 HTTP_INTERCEPTORS

所以场景如下: Cyclic Dependency

关于如何打破这个圈子的任何想法或建议? 有没有办法让 Auth服务 HttpClient 独立于 AuthInterceptor ?或者这是一个坏主意? (另外第三个功能将被添加到 AuthService ,用于将用户注销,其请求将被截获并且还将Authorization标头添加到其中)

到目前为止,我发现了类似的issue,但是解决方法表明我的问题没有解决,现在我在发送任何请求之前在引导过程中得到无限递归。我已经处理了拦截登录和令牌刷新请求以避免this的情况,所以据我所知,这不是问题所在。 这是plunk,其中包含我的代码概述。

从插件中摘录:

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  private auth: AuthService;

  constructor(inj: Injector) {
    this.auth = inj.get(AuthService);
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // Ignore if login or refresh request
    if (req.url.includes('login')) {
      return next.handle(req);
    }

    console.log('Intercepting request...');
    return this.auth.getToken().map(token => {
      const authHeader = 'Bearer ' + token;
      const authReq = req.clone({setHeaders: {Authorization: authHeader}});
      return authReq;
    }).concatMap(newReq => next.handle(newReq));
  }
}

4 个答案:

答案 0 :(得分:6)

尝试使用超时设置this.auth

constructor(private injector: Injector) {
  setTimeout(() => {
    this.auth = this.injector.get(AuthService);
  })
}

您已链接到的错误报告已更新,并提供了替代解决方法(在拦截函数中检索AuthService /而不是在构造函数中设置它):https://github.com/angular/angular/issues/18224#issuecomment-316957213

答案 1 :(得分:4)

更新08/02/2018 - angular 5.2.3

只是对此的更新:这是在角度5.2.3

中修复的

https://github.com/angular/angular/blob/master/CHANGELOG.md#bug-fixes-2

因此,您可以在HttpInterceptors中直接注入依赖于HttpClient的服务

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

    constructor(private auth: AuthService) 

答案 2 :(得分:1)

我在使用Angular 6.1.10时遇到了相同或相似的问题。我只是自己在需要注入HttpInterceptor的服务中实例化HttpClient:

@Injectable()
export class AuthService {

  private http: HttpClient;

  constructor(httpBackend: HttpBackend) {
    this.http = new HttpClient(httpBackend);    
  }
}

这打破了我的无限循环问题。

答案 3 :(得分:0)

我的问题是在注入到 HttpInterceptor 的服务构造函数中使用了 HttpClient。

export class SettingsService {
    constructor(
        private http: HttpClient,
    ) {
        this.http.get(...).subscribe() => {
            ...
        });
    }
}

export class AppInterceptor implements HttpInterceptor {
    constructor(
        private settingsS: SettingsService,
    ) { }
    ...
    ...
}