RoyalSausage
RoyalSausage

Reputation: 35

Rxjs / Angular 8: HTTPHandler doesn't get triggered when calling Subscription.unsubscribe()

I need to unsubscribe during a call but when I do this there is no HttpResponse. This is a problem for me as I also am using an http interceptor to catch when I should show a loading icon or not.

So in my specific component I have this:

 if (this.testSubscription)
    this.testSubscription.unsubscribe();  // Stop original http request when calling getTestDetails with other parameters
  this.testSubscription = this.getTestDetails(param1, param2);

And my interceptor:

 intercept(request: HttpRequest<any>, next: HttpHandler) {
this.totalRequests++;
console.log(' intercept totalRequests: ', this.totalRequests);
this.loadingService.isLoading.next(true);
return next.handle(request).pipe(
  tap(res => {
    if (res instanceof HttpResponse) {
    //  I need to get here even when unsubscribing !!!!
        this.decreaseRequests();
    }
  }),
  catchError(err => {
    this.decreaseRequests();
    throw err;
  })
);
}

So I'm not really sure how I can trigger my intercept method to catch this when I unsubscribe on the Subscription.. Any ideas are appreciated!

Upvotes: 1

Views: 149

Answers (2)

Dmitry Efimenko
Dmitry Efimenko

Reputation: 11203

This code looks vaguely familiar. :D

As @martin pointed out, you can use the finalize operator. In fact, I've done some testing and found out you don't even need to tap operator to handle all use-cases:

return next.handle(request).pipe(
  finalize(() => {
    this.totalRequests--;
    if (this.totalRequests === 0) {
      console.log('set loading false');
    }
  })
);

I've updated the original answer to reflect this info.

PS: The solution you came up with might have a bug in case of an error. If you have two pending requests and one of them fails while the other one is still in progress, you'll have decreaseRequests() run twice (one from catchError operator and one from finalize), which will set loading to false even though there still is another request pending.

Upvotes: 1

RoyalSausage
RoyalSausage

Reputation: 35

Thanks to the comments I was able to fix my problem. I've changed my interceptor to:

  intercept(request: HttpRequest<any>, next: HttpHandler) {
this.totalRequests++;
this.loadingService.isLoading.next(true);
return next.handle(request).pipe(
  tap(res => {
  //Removed code here
  }),
  catchError(err => {
    this.decreaseRequests();
    throw err;
  }),
  finalize(() => {
    if(this.totalRequests > 0){
      this.decreaseRequests();
  }  }
  )
);

}

I've tested it thoroughly and it seems to be working for my purposes.

Upvotes: 0

Related Questions