注入服务时Angular 5 Http Interceptors错误

dev*_*ev7 15 dependency-injection angular-http-interceptors angular

在角度5+中使用自定义HttpInterceptors时,我收到以下奇怪的依赖注入行为.

以下简化代码工作正常:

    export class AuthInterceptor implements HttpInterceptor {
        constructor(private auth: AuthService) {}

        intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
            const token = this.auth.getToken();
            return next.handle(req);
        }
    }
    export class AuthService {
        token: string;
        constructor() {
          console.log('AuthService.constructor');
        }
    }
Run Code Online (Sandbox Code Playgroud)

然而....

AuthService具有1个或更多依赖性时,例如

   export class AuthService {
      token: string;
      constructor(private api: APIService) {
         console.log('AuthService.constructor');
      }
   }
Run Code Online (Sandbox Code Playgroud)

angular尝试重复创建新实例,AuthService直到收到以下错误:

日志显示AuthService.constructor消息~400次

Cannot instantiate cyclic dependency! HTTP_INTERCEPTORS ("[ERROR ->]"): in NgModule AppModule

app.component.html:44错误RangeError:超出最大调用堆栈大小

然后我尝试使用Injector类注入服务 -

 export class AuthService {
      token: string;
      api: APIService;
      constructor(private injector: Injector) {
         this.api = this.injector.get(APIService);
         console.log('AuthService.constructor');
      }
   }
Run Code Online (Sandbox Code Playgroud)

但得到相同的错误(最大调用堆栈大小).

APIService是一个简单的服务,只注入HttpClient其构造函数.

@Injectable()
export class APIService {
    constructor(private http: HttpClient) {}
}
Run Code Online (Sandbox Code Playgroud)

最后,当我AuthService使用the 注入Interceptor时Injector,错误消失但AuthService被实例化200次以上:

export class AuthInterceptor implements HttpInterceptor {
    auth: AuthService;
    constructor(private injector: Injector) {}
    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
           this.auth = this.auth || this.injector.get(AuthService);
           const token = this.auth.getToken();
           return next.handle(req);
        }
    }
Run Code Online (Sandbox Code Playgroud)

看看官方文档和其他示例,似乎技术上可以将服务注入Http拦截器.是否有任何限制或任何其他设置可能会丢失?

小智 11

2018年1月底更新

Angular Team在2018年1月31日发布的Angular 5.2.3中解决了这个问题.更新角度版本之后,您将能够在构造函数中正常注入使用HTTPClient的服务

Bug修复

common:允许HttpInterceptors注入HttpClient(#19809)(ed2b717),关闭#18224

来自Angular changelog


dev*_*ev7 8

事实证明,如果您注入Http Interceptor的服务具有依赖性HttpClient,则会导致循环依赖.

由于我AuthService是所有不同逻辑(登录/退出,路由用户,保存/加载令牌,进行api调用)的混合,我将拦截器所需的部分分离为自己的服务(仅用户凭证和令牌),现在将它成功注入拦截器.

export class AuthInterceptor implements HttpInterceptor {
    constructor(private credentials: CredentialsService) {}
    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        const token = this.credentials.getToken();
        const api_key = this.credentials.getApiKey();
    }
}

export class CredentialsService {
    token: string;
    user: IUser;
    constructor(private http: HttpClient) {
        this.loadCredentialsFromStorage();
    }
}
Run Code Online (Sandbox Code Playgroud)

这似乎工作正常.希望这有助于某人.

  • 代码与您的第一行相矛盾,在您的代码中您注入了一个依赖于 HttpClient 的服务,那么这如何解决问题 (2认同)