为什么我要使用 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 的解决方案(interval
、timer
)允许您通过管道传递条件运算符(例如 takeWhile
、skipWhile
),这允许您只需翻转一个布尔标志即可添加停止或实现停止-启动逻辑,而不是添加清除间隔然后重新创建的复杂逻辑。
而且它们是可观察的,您可以在整个应用程序中监听它们,并附加任意数量的监听器。
错误处理也更好,您订阅所有成功,并在 catch 回调中处理所有内容。
RxJS 的优势:
懒惰
您可以创建您的 Observables,在您调用 subscribe
之前什么都不会发生。可观察 = 纯函数。这给了你更多的控制权,更容易的推理,并允许下一点......
可组合性
您可以将 interval/timer
与其他 operators
以统一的方式轻松创建自定义逻辑 - 例如,您可以 map
、repeat
、retry
, take
...等等 see all operators
错误处理
如果出现错误,您有责任调用 clearTimeout/clearInterval
- Observables 正在为您处理。导致 更清晰的代码 和 更少的内存泄漏 错误。
当然,任何你用 Observables 做的事情你也可以不用 Observables 做——但这不是重点。 Observables 在这里让您的生活更轻松。
另请注意,interval/timer
不是用于轮询的良好可观察工厂,因为它们不会 "wait" 让您的异步操作完成(您最终可能会有多个异步调用 运行彼此)。为此,我倾向于像这样使用 defer
和 repeatWhen
:
defer(() => doAsyncAction())
.pipe(
repeatWhen(notifications => notifications.pipe(delay(1234)))
);
用例:每分钟(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 函数设置间隔或执行轮询有很大好处,这些好处在
window.setInterval
不关心你的回调状态,它会在给定的时间间隔执行,不管过去回调的执行状态如何,让它停止和跳过的唯一方法很明确间隔或重新初始化它。
另一方面,基于 RxJS Observable 的解决方案(interval
、timer
)允许您通过管道传递条件运算符(例如 takeWhile
、skipWhile
),这允许您只需翻转一个布尔标志即可添加停止或实现停止-启动逻辑,而不是添加清除间隔然后重新创建的复杂逻辑。
而且它们是可观察的,您可以在整个应用程序中监听它们,并附加任意数量的监听器。
错误处理也更好,您订阅所有成功,并在 catch 回调中处理所有内容。
RxJS 的优势:
懒惰
您可以创建您的 Observables,在您调用 subscribe
之前什么都不会发生。可观察 = 纯函数。这给了你更多的控制权,更容易的推理,并允许下一点......
可组合性
您可以将 interval/timer
与其他 operators
以统一的方式轻松创建自定义逻辑 - 例如,您可以 map
、repeat
、retry
, take
...等等 see all operators
错误处理
如果出现错误,您有责任调用 clearTimeout/clearInterval
- Observables 正在为您处理。导致 更清晰的代码 和 更少的内存泄漏 错误。
当然,任何你用 Observables 做的事情你也可以不用 Observables 做——但这不是重点。 Observables 在这里让您的生活更轻松。
另请注意,interval/timer
不是用于轮询的良好可观察工厂,因为它们不会 "wait" 让您的异步操作完成(您最终可能会有多个异步调用 运行彼此)。为此,我倾向于像这样使用 defer
和 repeatWhen
:
defer(() => doAsyncAction())
.pipe(
repeatWhen(notifications => notifications.pipe(delay(1234)))
);