angularhttphttpclientcyclic-dependency

Angular Provider, Cyclic Dependency Error


I get this error:
Provider parse errors: Cannot instantiate cyclic dependency!

I have a Component to make http calls to my backend:
backend.component.ts

import { HttpClient } from '@angular/common/http';
public basicQuery(): void {
  this.httpClient.get('http://...')
    .subscribe(
    (response) => {

    },
    error => {

    });
}

I use interceptor for every call.
token.interceptor.ts

public intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  request = request.clone({
    setHeaders: {
      token: this.auth.getToken()
    }
  });

  return next
    .handle(request)
    .do(
    (response: HttpEvent<any>) => {
    },
    (error: any) => {
      return false;
  });
}

If i get an error, i handle this in my custom error handler because i want to send the error to my backend.
custom-error-handler.ts

handleError(error): void {
  this.errorLogService.logServer(error);
  super.handleError(error);
}

Therefor i use a service.
errorLog.service.ts

import { HttpClient } from '@angular/common/http';
logServer(error: Error) {
  this.httpClient.post('http://...', JSON.stringify(error.message))
    .subscribe(
    (response) => { },
    (error) => { });
}

And here is the problem, because i use also the httpClient. But how can i avoid this failure, how do it right? Right now i use 'Http' instead of 'HttpClient'.

Update 1

private auth: AuthService;

constructor(
  private utils: Utils,
  private router: Router,
  private injector: Injector
) {
  this.auth = this.injector.get(AuthService);
}

public intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  request = request.clone({
    setHeaders: {
      token: this.auth.getToken()
    }
  });

  return next
    .handle(request)
    .do(
      (response: HttpEvent<any>) => { },
      (error: any) => { return false }
    );
}

Update 2

Injecting the AuthService and Router into the body fixes the problem:

public intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  const started = Date.now();

  this.auth = this.injector.get(AuthService);
  this.router = this.injector.get(Router);

  (...)
}

Solution

  • Here is how you could do this, Do not inject the service in the constructor instead do that in your function body. Here you would also not run into the issues like maximum call reached.

    @Injectable()
    export class YourInterceptor implements HttpInterceptor {
      yourService: YourService;
      constructor(private inject: Injector) {
        //this.yourService = inject.get(YourService);
      }
    
      intercept(
        request: HttpRequest<any>,
        next: HttpHandler
      ): Observable<HttpEvent<any>> {
    
        this.yourService = this.inject.get(YourService);
    
        request = request.clone({
           setHeaders: {
              token: this.YourService.getToken()
           }
        });
    
        return next.handle(request);    
      }
    }
    

    As per your constructor try this,

    private auth: AuthService;
    private router: Router;
    
    constructor(
      private utils: Utils,
      private injector: Injector
    ) {
    
    }
    
    public intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
      this.router = this.injector.get(Router);
      this.auth = this.injector.get(AuthService);
      request = request.clone({
        setHeaders: {
          token: this.auth.getToken()
        }
      });
    
      return next
        .handle(request)
        .do(
          (response: HttpEvent<any>) => { },
          (error: any) => { return false }
        );
    }