Search code examples
angularangular-http-interceptors

Inject http interceptor at component


I've created this http interceptor:

@Injectable()
export class NoopInterceptor  implements HttpInterceptor {
    public my_status: boolean = true;
    private _statusChange: Subject<boolean> = new Subject<boolean>();
    public statusChange$ = this._statusChange.asObservable();
    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        this.changeStatus(false);
        const my_req = req.clone({
            url: API_PATH + req.url
        });
        return next
            .handle(my_req)
            .do(event => {
                if (event instanceof HttpResponse)
                    this.changeStatus(true);
            });
    }

    private changeStatus(status: boolean) {
        this.my_status = status;
        this._statusChange.next(this.my_status);
    }
}

And in my component, I did it:

export class AppComponent implements OnInit {
    public my_status: boolean;
    constructor(private httpInterceptor: NoopInterceptor) {
        this.my_status = httpInterceptor.my_status;
        httpInterceptor.statusChange$.subscribe(this.changeStatus);
    }

    changeStatus(status: boolean) {
        this.my_status = status;
    }

}

At app.module, I provided the interceptor like this:

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

When I do in the way above, I get No provider for NoopInterceptor!, because I'm not providing NoopInterceptor, but if I provide NoopInterceptor like this:

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

I'll get two injections and the component will get the wrong one, then I won't be able to subscribe statusChange. How can I workaround this?


Solution

  • It's likely possible to create single interceptor instance with:

    providers: [
        NoopInterceptor,
       {
            provide: HTTP_INTERCEPTORS,
            useExisting: NoopInterceptor,
            multi: true
        }
    ]
    

    But a proper solution for loading indicator state (I guess statusChange serves for this purpose) is to detach it from an interceptor and make it a separate provider.

    And as it's shown here, there should be request counter because there can be simultaneous requests, and it should be affected by both success and error do callbacks.