Angular 角度:如何在定期请求时取消订阅
我有一个角度组件,定期从服务请求值:Angular 角度:如何在定期请求时取消订阅,angular,rxjs,Angular,Rxjs,我有一个角度组件,定期从服务请求值: setInterval(() => { this.updateValues(); }, 1000); updateValues(): void { if (this.isValuesUpdateRunning === false) { this.isValuesUpdateRunning = true; this.apiService.getCurrentValues().subscribe((data: a
setInterval(() => {
this.updateValues();
}, 1000);
updateValues(): void {
if (this.isValuesUpdateRunning === false) {
this.isValuesUpdateRunning = true;
this.apiService.getCurrentValues().subscribe((data: any) => {
if (data != null) {
this.currentValues = data;
this.isValuesUpdateRunning = false;
}
});
}
}
我很确定我应该在某个地方取消订阅这项服务,因为我确实通过这样做打开了很多订阅。我正在考虑使用异步管道,但是我需要设置“isValueUpdateRunning”变量,如果我只是在模板中使用异步,这是不可能的
另外,在Angular提供的“onDestroy”方法中取消订阅也没有帮助,因为据我所知,这个方法只有在我离开页面时才会被调用。但我需要更频繁地关闭订阅,以防止数千个订阅保持打开状态
我还尝试在设置值后立即关闭订阅,但在视图中没有任何值:
updateValues(): void {
if (this.isValuesUpdateRunning === false) {
this.isValuesUpdateRunning = true;
const sub = this.apiService.getCurrentValues().subscribe((data: any) => {
if (data != null) {
this.currentValues = data;
this.isValuesUpdateRunning = false;
}
});
// closing the subscription right here:
sub.unsubscribe();
}
}
你能帮忙吗?我已经没有主意了。如果使用的是angular http客户端,您不需要像@Kurt Hamilton提到的那样取消订阅服务。您需要停止正在创建订阅的设置间隔 使用rxjs运算符的示例
interval(1000)
.pipe(
takeWhile(() => this.isValuesUpdateRunning), // call subscription until the condition is false
switchMap(() => this.apiService.getCurrentValues()),
filter(Boolean), // check if response is not null
tap(resp => { this.data = resp; this.isValuesUpdateRunning = false; }),
// handle errors
您可以在收到如下所示的响应后关闭订阅。另外,请注意,如果从getCurrentValues()调用AJAX API,则HTTPObservable是自动关闭的,因为一旦获得http响应,http客户端将完成订阅,因此无需关闭订阅
updateValues(): void {
if (this.isValuesUpdateRunning === false) {
this.isValuesUpdateRunning = true;
const sub = this.apiService.getCurrentValues().subscribe((data: any) => {
if (data != null) {
this.currentValues = data;
this.isValuesUpdateRunning = false;
}
// closing the subscription right here:
sub.unsubscribe();
}, error => { sub.unsubscribe});
}
}
假设您正在模板中呈现
currentValues
,我建议使用异步管道
根据isValuesUpdateRunning
逻辑,您可以使用defaustmap
并用RxJS间隔替换setTimeout
我在下面放了一个演示—我强烈建议您学习模拟api服务,并亲自尝试这些东西
const currentValues$ = interval(1000)
.pipe(
tap(i => console.log(`timer::${i}`)),
exhaustMap(i => apiService.getCurrentValues(i)), // ignores new values until api returns
tap(apiData => console.log(`api::${apiData}`)),
filter(data => !!data) // filter for truthy values
takeUntil(stopClick$), // or this.destroyed$ component logic
)
(这假设在模板中使用异步管道,例如{{currentValues$|async | json}}
)
更新-最好把take放在最后
工具书类
-如果此.apiService.getCurrentValues()正在使用angular
HttpClient发出http请求,则忽略新发出的值,直到当前observable完成(angular http请求自动完成),你不需要取消订阅。你没有获得价值,因为你在得到答案之前没有订阅。我同意上面关于http请求的评论。@KurtHamilton我正在使用HttpClient,是的。这只是一个简单的get请求。你觉得我根本不需要退订?我认为它总是需要的,除非你使用异步管道。@Manuela取消订阅并没有什么坏处,事实上,如果你不想让subscribe中的逻辑运行,比如api调用挂起,并且你移动到了应用程序的另一个部分,而这不是必须的。更新后,问题似乎是我今天早上没有喝咖啡。很抱歉成为那个家伙,但这将立即取消订阅takeUntil
将立即从BehaviorSubject
接收一个值<代码>条件$
只能是普通的ol'主题
。更新的示例。不,这很好,我有错误的假设,你完全正确。检查了文档。也许使用takeWhile和使用变量的谓词是正确的方法。我的想法有点不同,我想使用这个值,而不是触发订阅。