如果仍在进行中,则不应重置 Rxjs 间隔请求,但如果用户更改输入,则应重置

Rxjs Interval request should not reset if still ongoing, but should reset if user changes input

提问人:DeejC 提问时间:11/17/2023 更新时间:11/18/2023 访问量:23

问:

我有一个可观察对象,它结合了间隔和日期选择操作。我使用 and 对这两个可观察对象发出请求。这个想法是用户正在查看特定日期的表(可以随时更改),并且该表应每 20 秒更新一次(此时间可由用户配置)。combineLatestswitchMap

data$ = combineLatest(
    this.refreshInterval$,
    this.dateSelected$
).pipe(
    switchMap(([_, date]) => this.requestDataForDate(date))
);

这有效,除非请求花费的时间超过 20 秒。如果请求耗时较长,则每次触发间隔时,它都会取消正在进行的请求并发出新的请求。这是有道理的,因为我使用的是 ,如果我更改为 ,那么这不会发生。switchMapconcatMap

但是,如果用户更改了日期,则应发出另一个请求,并取消前一个请求,这在使用 .concatMap

我怎样才能同时实现这两个目标?如果用户更改了日期,则无论如何都应重新提交请求,但如果在请求正在进行时触发了间隔,则不应重新提交请求

角度 rxjs

评论


答:

0赞 MoxxiManagarm 11/18/2023 #1

我认为这在一个流 tbh 中是不可能的。

我能想到的最好的办法是创建 2 个流,然后将结果放入一个主题中。

data$ = dataSubject.asObservable();

this.refreshInterval$.pipe(
  withLatestFrom(this.dateSelected$)
  exhaustMap(([_, date]) => this.requestDataForDate(date)),
  // some unsubscription
).subscribe(data => dataSubject.next(data));

this.dateSelected$.pipe(
  switchMap(date => this.requestDataForDate(date)),
  // some unsubscription
).subscribe(data => dataSubject.next(data));
2赞 akotech 11/18/2023 #2

作为基础,您可以:dateSelected$

  • 首先到switchrefreshInterval$

  • 然后是请求的间隔exhaust|concat

    data$ = this.dateSelected$.pipe(
      switchMap((date) => 
        this.refreshInterval$.pipe(exhaustMap(() => this.requestDataForDate(date)))
      )
    );
    

评论

0赞 MoxxiManagarm 11/18/2023
我可能是错的,但这不会立即执行请求,只会在再次发出refreshInterval$时发出。在这种情况下,应创建一个新的可观察区间。好处:一旦日期更改,计时器也会再次启动
0赞 akotech 11/18/2023
@MoxxiManagarm你是完全正确的。但我假设他/她正在使用一个在订阅时立即发出的间隔(即)。否则,在他/她的原始示例中,还必须等待间隔触发第一个数据请求。timer(0,interval)
1赞 DeejC 11/20/2023
是的,你是对的,@akotech,我使用的是立即发射的计时器,所以你的解决方案效果很好。谢谢!