为什么我要使用 RxJS interval() 或 timer() 轮询而不是 window.setInterval()?

Why would I use RxJS interval() or timer() polling instead of window.setInterval()?

用例:每分钟(60000 毫秒)调用一个函数,该函数调度存储操作以获取 lastUpdated 项的状态,根据响应和过滤,更新存储,更新后的存储被读取为可观察对象并显示在视图中)。只要 Web 应用程序打开(无限期),就需要发生这种情况。

目前,我正在使用这个:

this.refreshDate = window.setInterval(
  () => this.store.dispatch(new FetchLastUpdate())
, 60000);

当视图为 destroyed/dismounted 时,我删除了间隔:

if (this.refreshDate) {
  clearInterval(this.refreshDate);
}

这是efficient/effective,还是很麻烦?

为什么我要使用像这样的 RxJS 轮询策略:

interval(60000)
  .pipe(
    startWith(0),
    switchMap(() => this.store.dispatch(new FetchLastUpdate()))
   );

timer(0, 60000)
  .pipe(
    switchMap(() => this.store.dispatch(new FetchLastUpdate()))
  );

TL;DR: window.setInterval() 对比 RxJS timer()/interval()


Conclusion/answers(为了便于研究):

使用 RxJS 函数设置间隔或执行轮询有很大好处,这些好处在 和评论中都有解释,但得出的结论是(通过评论中的讨论)在这个post开头的“Use case”部分定义的非常简单的需求,没有必要使用RxJS,事实上如果你不使用RxJS你程序的任何其他部分,不要为此导入它,但就我而言,我已经在其他地方导入并使用了 RxJS。

window.setInterval 不关心你的回调状态,它会在给定的时间间隔执行,不管过去回调的执行状态如何,让它停止和跳过的唯一方法很明确间隔或重新初始化它。

另一方面,基于 RxJS Observable 的解决方案(intervaltimer)允许您通过管道传递条件运算符(例如 takeWhileskipWhile),这允许您只需翻转一个布尔标志即可添加停止或实现停止-启动逻辑,而不是添加清除间隔然后重新创建的复杂逻辑。

而且它们是可观察的,您可以在整个应用程序中监听它们,并附加任意数量的监听器。

错误处理也更好,您订阅所有成功,并在 catch 回调中处理所有内容。

RxJS 的优势:

懒惰

您可以创建您的 Observables,在您调用 subscribe 之前什么都不会发生。可观察 = 纯函数。这给了你更多的控制权,更容易的推理,并允许下一点......

可组合性

您可以将 interval/timer 与其他 operators 以统一的方式轻松创建自定义逻辑 - 例如,您可以 maprepeatretry , take...等等 see all operators

错误处理

如果出现错误,您有责任调用 clearTimeout/clearInterval - Observables 正在为您处理。导致 更清晰的代码 更少的内存泄漏 错误。

当然,任何你用 Observables 做的事情你也可以不用 Observables 做——但这不是重点。 Observables 在这里让您的生活更轻松。


另请注意,interval/timer 不是用于轮询的良好可观察工厂,因为它们不会 "wait" 让您的异步操作完成(您最终可能会有多个异步调用 运行彼此)。为此,我倾向于像这样使用 deferrepeatWhen

defer(() => doAsyncAction())
  .pipe(
    repeatWhen(notifications => notifications.pipe(delay(1234)))
  );