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
,即使还有另一个请求待处理。
我需要在通话期间 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
,即使还有另一个请求待处理。