In my angular app I'm seeing chrome (cancel) api calls that fire off too rapidly. I also have an HttpInterceptor that triggers a loading indicator with every HttpClient request after 500ms if the request has not completed. However, on the requests that get (cancelled) there does not seem to be any new event to subsequently hide my loading indicator.
Is there a way to detect 'cancelled' requests in the HttpInterceptor so I can hide my loading indicator again?
export class GlobalHttpInterceptor implements HttpInterceptor {
constructor(
private sessionService: SessionService,
private loadingService: LoadingService
) { }
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
setTimeout(() => {
if (showLoading) {
this.loadingService.show();
}
}, 500);
let showLoading = true;
if (this.sessionService.headers.length > 0) {
for (const x of this.sessionService.headers) {
req = req.clone({
headers: req.headers.set(x.key, x.value)
});
}
}
return next.handle(req)
.do(
(response) => {
if (response instanceof HttpResponse) {
showLoading = false;
this.loadingService.hide();
}
},
(error) => {
showLoading = false;
this.loadingService.hide();
}
);
}
}
Just encountered the same problem. The finalize operator seems to trigger even when the http request is cancelled.
public intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
// request starts
return next.handle(request).pipe(
finalize(() => {
// request completes, errors, or is cancelled
})
);
}
Expanding on Davy's answer, this is how I'm detecting an aborted request.
As he stated, finalize will always run on the observable source completing, which in this case is either a success response, an error response, or an aborted request.
The key to my approach is tracking what you have received so far.
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let lastResponse: HttpEvent<any>;
let error: HttpErrorResponse;
return next.handle(request)
.pipe(
tap((response: HttpEvent<any>) => {
lastResponse = response;
if (response.type === HttpEventType.Response) {
console.log('success response', response);
}
}),
catchError((err: any) => {
error = err;
console.log('error response', err);
// TODO: error handling if required
return throwError(err);
}),
finalize(() => {
if (lastResponse.type === HttpEventType.Sent && !error) {
// last response type was 0, and we haven't received an error
console.log('aborted request');
}
})
);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With