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?
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.