【问题标题】:HttpInterceptor->Service->HttpClient Cyclic DependencyHttpInterceptor->Service->HttpClient循环依赖
【发布时间】:2017-12-26 01:41:43
【问题描述】:

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

另一个“服务”是一个 HttpInterceptor,我想拦截所有传出请求除了由 AuthService 发出的请求以添加授权标头(现在变脏了)。为了构成该标头,我们需要一个从 AuthService 获得的令牌。也就是说,AuthInterceptor(我的拦截器的名字)依赖于AuthService。据我所知,HttpClient 依赖于所有 HTTP_INTERCEPTORS

所以场景如下:

关于如何打破这个圈子有什么想法或建议吗? 有没有办法让AuthServiceHttpClient独立于AuthInterceptor?或者这是一个坏主意? (另外第三个函数将被添加到 AuthService 用于注销用户,其请求将被拦截并添加授权标头)

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

摘自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));
  }
}

【问题讨论】:

    标签: angular


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

      @Injectable()
      export class AuthService {
      
        private http: HttpClient;
      
        constructor(httpBackend: HttpBackend) {
          this.http = new HttpClient(httpBackend);    
        }
      }
      

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

      【讨论】:

        【解决方案3】:

        2018 年 8 月 2 日更新 - 角度 5.2.3

        只是对此的更新:这已在 Angular 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) 
        

        【讨论】:

        • 不确定...它仍然给出错误Cannot instantiate cyclic dependency! HTTP_INTERCEPTORS
        • 奇怪,升级到 5.2.3 的我马上就解决了这个问题
        • 糟糕,对不起!我正在运行5.2.0。只需更新到最新版本,它就可以工作了。谢谢。
        • 我仍然/再次使用 Angular 6.1.10 遇到这个问题。我需要使用注入的 httpBackend 在 AuthService 中自己实例化 HttpClient,new HttpClient(httpBackend)
        【解决方案4】:

        尝试将this.auth 设置为超时:

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

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

        【讨论】:

        • 即使我在拦截函数中设置 AuthService 并使用注入器,这个问题仍然存在。
        猜你喜欢
        • 1970-01-01
        • 2018-12-10
        • 1970-01-01
        • 2010-09-12
        • 2021-10-02
        • 1970-01-01
        相关资源
        最近更新 更多