Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular: How to know if request has been cancelled in HttpClient

To know if a request has completed, I do if (httpEvent instanceof HttpResponse). Likewise, how to know if a request is cancelled in HttpInterceptor? Below is my intercept function.

intercept(httpRequest: HttpRequest<any>, httpHandler: HttpHandler): Observable<HttpEvent<any>> {
    this.requestsPending++;

    if (this.typeAheads.includes(httpRequest.url.split('/').pop()))
      this.slimLoadingBarService.start();
    else
      this.flsLoaderService.start();

    return httpHandler.handle(httpRequest)
      .do((httpEvent: HttpEvent<any>) => {
        if (httpEvent instanceof HttpResponse) {
          // decrementing counter on each request return
          this.requestsPending--;

          if (this.typeAheads.includes(httpEvent.url.split('/').pop())) {
            if (this.requestsPending === 0)
              this.slimLoadingBarService.complete();
          }
          else {
            if (this.requestsPending === 0)
              this.flsLoaderService.stop();
          }
        }
      }, () => {
        this.slimLoadingBarService.complete();

        // reset counter on error
        this.requestsPending = 0;
        this.flsLoaderService.stop();
      });
  }
like image 242
karthikaruna Avatar asked Nov 10 '17 08:11

karthikaruna


3 Answers

I have also had this problem and that's a solution to which I've came recently:

to know if a request was cancelled you can use finally operator, heres example:

let cancelled = true;
return next.handle(request).do(
  undefined,
  () => {
    // error
    cancelled = false;
  },
  () => {
    // completed
    cancelled = false;
  },
).finally(
  () => {
    if (cancelled) {
      // do things
    }
  },
);
like image 95
Roomy Avatar answered Sep 22 '22 00:09

Roomy


Finally I found a solution

intercept(httpRequest: HttpRequest<any>, httpHandler: HttpHandler):
    Observable<HttpEvent<any>> {

        this.requestsPending++;

        //...

        return new Observable(observer => {
            let sub = httpHandler.handle(httpRequest)
                .pipe(tap(event => {
                    //... your logic
                }))
                .subscribe(event => observer.next(event));

            return () => {
                if (!sub.closed) {
                    this.requestsPending--;
                    sub.unsubscribe();
                }
            };
        });
}
like image 20
Voskanyan David Avatar answered Sep 21 '22 00:09

Voskanyan David


to make it work, I used a mix of both techniques from above as they did not work out of the box for me. Here my working code:

// your increment logic here

return new Observable(observer => {
  let isCanceled = true;   << here
  const sub = next.handle(req)
    .pipe(
      tap(
       (rsp: HttpResponse<any>) => {
          if (rsp.type === HttpEventType.Response) {
            isCanceled = false;
            // your decrement logic here
          }
        },
        (rspError: HttpErrorResponse) => {
          isCanceled = false;
          // your decrement logic here
          throwError(rspError); // re-throw same e
        },
      ),
    )
    .subscribe(observer);  // << here

  return () => {
    if (isCanceled) {
      // your decrement logic here
      sub.unsubscribe();
    }
  };
});
like image 33
Gauthier Peel Avatar answered Sep 19 '22 00:09

Gauthier Peel