1

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!

Kiran Mistry
  • 2,614
  • 3
  • 12
  • 28
  • 1
    You can use `finalize` that is triggered also when you unsubscribe but in that case you won't have access to any `next` in case it passed successfully. – martin Feb 05 '20 at 07:29
  • 1
    Generally, you could use `switchMap` to smoothly unsubscribe from one stream and subscribe to another. – mbojko Feb 05 '20 at 07:47
  • Martin's comment was an easy fix, thanks for all the help guys! – RoyalSausage Feb 05 '20 at 08:20

2 Answers2

1

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.

Dmitry Efimenko
  • 10,973
  • 7
  • 62
  • 79
0

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.