1

I am getting the following: "Uncaught Error: Can't resolve all parameters for ErrorInterceptor: (?)" when trying to inject AuthenticationService.

error.interceptor.ts

import { Injectable } from '@angular/core';
import ...

import { AuthenticationService } from '@/_services';

@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
    constructor(private authenticationService: AuthenticationService) {}

    intercept(request: HttpRequest<any>, next: HttpHandler): 
    Observable<HttpEvent<any>> {
        return next.handle(request).pipe(catchError(err => {
            if (err.status === 401) {
                // auto logout if 401 response returned from api
                this.authenticationService.logout();
                location.reload(true);
            }

            const error = err.error.message || err.statusText;
            return throwError(error);
        }))
    }
}

authentication.service.ts

import { Injectable } from '@angular/core';
import ...

@Injectable({ providedIn: 'root' })
export class AuthenticationService {
private currentUserSubject: BehaviorSubject<User>;
public currentUser: Observable<User>;

constructor(private http: HttpClient) {
    this.currentUserSubject = new BehaviorSubject<User>(JSON.parse(localStorage.getItem('currentUser')));
    this.currentUser = this.currentUserSubject.asObservable();
}

public get currentUserValue(): User {
    return this.currentUserSubject.value;
}

login(username, password) {
    ...
}

logout() {
    ...
}
}

app.module.ts contains:

providers: [
    { provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true }
]

I am using Angular 8. Full error code:

Uncaught Error: Can't resolve all parameters for ErrorInterceptor: (?).
at syntaxError (compiler.js:2687)
at CompileMetadataResolver._getDependenciesMetadata (compiler.js:21355)
at CompileMetadataResolver._getTypeMetadata (compiler.js:21248)
at CompileMetadataResolver._getInjectableTypeMetadata (compiler.js:21470)
at CompileMetadataResolver.getProviderMetadata (compiler.js:21479)
at eval (compiler.js:21417)
at Array.forEach (<anonymous>)
at CompileMetadataResolver._getProvidersMetadata (compiler.js:21377)
at CompileMetadataResolver.getNgModuleMetadata (compiler.js:21096)
at JitCompiler._loadModules (compiler.js:27143)

1 Answer 1

2

The problem is circular dependency. AuthenticationService needs HttpClient, HttpClient needs Interceptors, ErrorInterceptor needs AuthenticationService.

In order to solve this, you need to separate AuthenticationService into two layers - one for storing the authentication data and one for the API communication.

class AuthenticationStore {
   storeData(authData) {}
   getData(): AuthData {}
   clearData() {}

Say you have the AuthenticationStore. Then the ErrorInterceptor would use the AuthenticationStore instead of AuthenticationService.

@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
    constructor(private authenticationStore: AuthenticationStore) {}

    intercept(request: HttpRequest<any>, next: HttpHandler): 
    Observable<HttpEvent<any>> {
        return next.handle(request).pipe(catchError(err => {
            if (err.status === 401) {
                // auto logout if 401 response returned from api
                this.authenticationStore.clearData();
                location.reload(true);
            }

            const error = err.error.message || err.statusText;
            return throwError(error);
        }))
    }
}

Or you can use injector, that's a bit dirtier solution.

@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
    constructor(private injector: Injector) {}

    intercept(request: HttpRequest<any>, next: HttpHandler): 
    Observable<HttpEvent<any>> {
        return next.handle(request).pipe(catchError(err => {
            if (err.status === 401) {
                // auto logout if 401 response returned from api
                const authenticationService = this.injector.get(AuthenticationService);
                authenticationService.logout();
                location.reload(true);
            }

            const error = err.error.message || err.statusText;
            return throwError(error);
        }))
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.