Angular 5 Http Interceptors error when injecting service

后端 未结 8 903
北海茫月
北海茫月 2021-02-05 05:43

I am receiving the following strange dependency injection behavior when using custom HttpInterceptors in angular 5+.

The following simplified code works fine:

         


        
相关标签:
8条回答
  • 2021-02-05 06:14

    I got a similar issue with the same design of an auth service coupled with an interceptor.

    @Injectable() AuthInterceptorService {
        constructor (authApi: AuthApiService) {}
        handle () {...do the job}
    }
    
    @Injectable() AuthApiService {
       constructor () {
           // ...do some setup with a request, such as to get current session
           // that leads to an indirect circular between 2 constructors. 
       }
    

    }

    In my case, i found the cause is that I try to start a http request in the auth service's constructor. At that point the injector seems haven't completed the registration of the auth service's instance, while the http client captures the new request and tried to instantiaze the interceptor again, since the previous interceptor instance was stuck in its constructor on the call stack too!

    That recursive invoke with two constructors, breaks the singleton pattern of the injector and leads to out of call stack.

    0 讨论(0)
  • 2021-02-05 06:17

    you need to add Injector into constructor and inject AuthService via injector

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

    don't forget import

    import {Injector} from '@angular/core';
    
    0 讨论(0)
  • 2021-02-05 06:19

    For me @Benjineer answar helped to provide as a dependency in app.module.ts the required sercvice.

    Although what is interensting, in the order you add as a dependency in app.module.ts you get it in the constructor of the service.

    For Example: in the app module you provide in the order of AuthService, ErroMsgService

    deps: [AuthService, ErrorMsgService]
    

    in the HttpInterceptor constructor you have to create them in the same order

     constructor(
        private authService: AuthService,
        private errorService: ErrorMsgService
        ) {}
    
    0 讨论(0)
  • 2021-02-05 06:21

    If in case, service class is declared in the same file of Injector class then service class should be declared and defined first. Followed by the Injector class where the service class injected as a dependency.

    Following above structure does resolves the problem in my case.

    0 讨论(0)
  • 2021-02-05 06:22

    Update on end of January 2018

    Angular Team resolved this issue in Angular 5.2.3 released 31 January 2018. After updating angular version you will be able to inject services that use HTTPClient as normal in constructor

    Bug Fixes

    common: allow HttpInterceptors to inject HttpClient (#19809) (ed2b717), closes #18224

    from Angular changelog

    0 讨论(0)
  • 2021-02-05 06:26

    So it turns out that if the service you inject into the Http Interceptor has a dependency on HttpClient, this leads to a cyclic dependency.

    Since my AuthService was a mix of all different logics (login/out, routing the user, saving/loading tokens, making api calls), I separated the part needed for the interceptors into its own service (just the user credentials & tokens) and now injecting it successfully into the Interceptor.

    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();
        }
    }
    

    This seems to work fine. Hope this helps someone.

    0 讨论(0)
提交回复
热议问题