Why would I use RxJS interval() or timer() polling instead of window.setInterval()?
用例:每分钟(60000 ms)调用一个函数,该函数调度存储操作以获取项目的lastUpdated状态,该状态在响应和过滤后更新存储,并且更新的存储被视为可观察并显示在看法)。只要Web应用程序处于打开状态(无限期),就需要执行此操作。
当前,我正在使用此:
1 2 3
| this.refreshDate = window.setInterval(
() => this.store.dispatch(new FetchLastUpdate())
, 60000); |
当视图被破坏/卸除时,我将间隔删除为:
1 2 3
| if (this.refreshDate) {
clearInterval(this.refreshDate);
} |
这是有效/有效的还是麻烦的?
我为什么要使用RxJS轮询策略,例如:
1 2 3 4 5
| interval(60000)
.pipe(
startWith(0),
switchMap(() => this.store.dispatch(new FetchLastUpdate()))
); |
或
1 2 3 4
| timer(0, 60000)
.pipe(
switchMap(() => this.store.dispatch(new FetchLastUpdate()))
); |
TL; DR:window.setInterval()与RxJS timer() / interval()
结论/答案(为了便于研究):
使用RxJS函数设置时间间隔或执行轮询有很大的好处,这些好处不仅在选定的答案中也在注释中得到了解释,但是结论(通过注释中的讨论)得出的结论是,定义了非常简单的要求在本文开头的"用例"部分中,没有必要使用RxJS,实际上,如果您在程序的任何其他部分未使用RxJS,则不要仅为此目的导入它,但是在我的情况下,我已经在其他地方导入并使用过RxJS。
- 我认为FetchLastUpdate的持续时间不会超过60秒,因此使用switchMap似乎有些过分,我宁愿使用setInterval来满足您的使用情况
-
@OlivierBoissé对,这就是我一直想做的事情,但是我想我会寻求其他更有经验的意见。至于switchMap,您说得对,轻按可能会更好。
-
此外,添加rxjs会增加您的js包大小,因此如果您在其他地方不需要它,则可以跳过它并使用setInterval
-
@OlivierBoissé是的,尽管由于您提到(在其他地方使用它)的原因,它不适用于我。谢谢 :)
RxJS的优点:
懒惰
您可以创建自己的Observable,直到调用subscribe都没有任何反应。可观察=纯函数。这给您更多的控制权,更容易的推理,并允许下一点...
可组合性
您可以将interval/timer与其他operators结合在一起,以统一的方式非常轻松地创建自定义逻辑-例如,您可以map,repeat,retry,take ...等。查看所有运算符
错误处理
如果发生错误,则您负责调用clearTimeout/clearInterval-Observables将为您处理此问题。导致代码更简洁,内存泄漏错误更少。
当然,您对Observables所做的任何事情也可以在没有Observables的情况下进行-但这不是重点。可观察的物体在这里使您的生活更轻松。
还请注意,interval/timer不是可观察的良好工厂,因为它们不会"等待"异步操作完成(您可能最终会在彼此之间运行多个异步调用)。为此,我倾向于像这样使用defer和repeatWhen:
1 2 3 4
| defer(() => doAsyncAction())
.pipe(
repeatWhen(notifications => notifications.pipe(delay(1234)))
); |
-
谢谢您提供信息丰富的答案,这些绝对是我下次下次轮询时会考虑的问题,或者类似的东西,因此您的答案对interval() / <x4的好处的总体思路有所帮助>(或defer())与纯JS,但是考虑到我在帖子本身中定义的用例,我看不到这种使用会获得任何好处。
-
当然,如果您没有将rxjs用作其他用途,请使用window.setInterval,但请确保您的FetchLastUpdate操作所用的时间不要超过60秒:)
-
另外,为澄清为什么我看不到该用例有什么好处,我还发表了另一条评论:如果只需要每分钟调用一个函数,则无需创建一个完整的(干净的)逻辑。我不需要任何错误处理,因为我的FetchLastUpdate()动作可以处理所有它自己的错误,存储可以处理自己的错误以及异步HTTP调用。但是,自动清理很有用,因此我不必调用clearInterval(),但是我不确定调用RxJS函数来避免这种开销是否值得。尽管我可能高估了这一点。
-
(这是对您的评论答复的答复)好的,这很不错。 @OlivierBoissé也支持该声明。谢谢 :)
-
由于信息布局清晰,我选择了您的答案作为帖子的答案,并且它代表了这种RxJS策略而非纯JS的普遍使用。 @OlivierBoissé的答案是此用例的最终答案,但他没有发表答案,只是发表了评论。
window.setInterval不在乎您的回调状态,尽管已执行了过去的回调,它也会以给定的间隔执行,使其停止并跳过的唯一方法是清除间隔或重新初始化它。
另一方面,基于RxJS Observable的解决方案(interval,timer)允许您通过管道传递条件运算符(例如takeWhile,skipWhile),该条件运算符允许您添加停止符或实现停止符-通过翻转布尔值标志开始逻辑,而不是添加清除间隔然后重新创建的复杂逻辑。
它们是可观察的,您可以在应用程序中全部监听它们,并在其上附加任意数量的监听器。
错误处理也更好,您订阅所有成功,并处理catch回调中的所有内容。
- 错误的!如果window.setInterval具有基于XHR的回调,则可以使用async / await使其等待。 Ramda和其他图书馆只是一个过分的杀伤力。
-
@Adeel您有示例代码可以执行建议的操作吗?据我了解,即使在最后一个回调完成之前,也无法防止setInterval再次运行回调吗?
-
感谢您的答复。在@ m1ch4ls的帖子之前,我没有看到您的帖子,对此我发表了评论。但基本上,您是对的,下次我再进行轮询或其他任何事情时,我一定会考虑这些问题,因为我以前从未考虑过它们。方便,干净地访问这些操作员,以及更灵活的错误处理,这是非常有利的。阅读这些内容的其他案例/人将从这些方面受益,但是我看不到这些将如何使我的具体案例受益。我将其他评论的原因粘贴到此处的下一个评论中。
-
另外,为澄清为什么我看不到该用例有什么好处,我还发表了另一条评论:如果只需要每分钟调用一个函数,则无需创建一个完整的(干净的)逻辑。我不需要任何错误处理,因为我的FetchLastUpdate()动作可以处理所有自己的错误,存储可以处理自己的错误以及异步HTTP调用。但是,自动清理很有用,因此我不必调用clearInterval(),但是我不确定调用RxJS函数来避免这种开销是否值得。尽管我可能高估了这一点。
-
@Chris这是一个快速示例,我编写了codeandbox.io/s/q80j06y516,请注意,在此示例中,我在哪里获取随机用户。我可以将其package在try / catch中,并清除间隔并执行错误处理。希望这可以帮助。