Rxjs / Angular 8: HTTPHandler 在调用 Subscription.unsubscribe() 时没有被触发

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

我需要在通话期间 unsubscribe,但是当我这样做时没有 HttpResponse。这对我来说是个问题,因为我也在使用 http 拦截器来捕捉何时应该显示加载图标。

所以在我的特定组件中我有这个:

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

还有我的拦截器:

 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;
  })
);
}

所以我不太确定当我在订阅上 unsubscribe 时如何触发我的拦截方法来捕获它.. 任何想法表示赞赏!

多亏了评论,我才得以解决我的问题。 我已将拦截器更改为:

  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();
  }  }
  )
);

}

我已经对其进行了彻底的测试,它似乎可以满足我的目的。

此代码看起来 vaguely familiar。 :D

正如@martin 指出的那样,您可以使用 finalize 运算符。事实上,我做了一些测试,发现你甚至不需要 tap 运算符来处理所有用例:

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

我已经更新了原始答案以反映此信息。

PS:你想出的方案可能有bug,以防出错。如果您有两个待处理的请求,其中一个失败而另一个仍在进行中,您将有两次 decreaseRequests() 运行(一个来自 catchError 运算符,一个来自 finalize),这会将加载设置为 false,即使还有另一个请求待处理。