提问者:小点点

Angular:定期请求时如何取消订阅


我有一个角度组件,我定期从服务请求值:

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

我很确定我应该在某个地方取消订阅该服务,因为我确实通过这样做打开了很多订阅。我在考虑使用异步管道,但是我需要设置“isValueUpdateR不”变量,如果我只是在模板中使用异步,这是不可能的。

此外,在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();
  }
}

你能帮忙吗?我没有主意了。


共3个答案

匿名用户

获得响应后,您可以关闭订阅,如下所示。另请注意,如果您从getCurrentValue()调用AJAXAPI,HTTPContable是自动关闭的,您不需要关闭订阅,因为一旦您获得超文本传输协议,响应订阅将由角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});

      }
    }

匿名用户

假设您在模板中呈现当前值,我建议使用异步管道。

根据isValuesUpdateRruning逻辑,您可以使用在一个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
  )

(这假设模板中使用异步管道,例如{{当前值$|async|json}}

更新-最好把采取直到最后!

AftustMap-忽略新发出的值,直到当前可观察完成(角超文本传输协议请求自动完成)

匿名用户

如果使用角度超文本传输协议客户端,您不需要取消订阅@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