Angular 组件和服务是不是应该始终避免使用 setInterval(或 rxjs 计时器)?

Posted

技术标签:

【中文标题】Angular 组件和服务是不是应该始终避免使用 setInterval(或 rxjs 计时器)?【英文标题】:Should Angular components and services always avoid using setInterval (or rxjs timer)?Angular 组件和服务是否应该始终避免使用 setInterval(或 rxjs 计时器)? 【发布时间】:2021-01-28 16:44:24 【问题描述】:

我有一些组件和服务在后台定期执行操作——刷新数据、更新显示的日期/时间等。我最初使用setInterval 编写了这些功能。现在,我要回去添加单元测试。我花了方式太长时间试图弄清楚为什么我的测试不工作 - 事实证明,如果被测组件(或其任何依赖项!)创建间隔,fixture.whenStable() 将永远无法解决.我尝试从 setInterval 切换到 rxjs interval / timer,但它们有同样的问题。

在this older question 上给出的建议是将实际的setInterval 调用放在专用的“间隔服务”中,然后在编写测试时使用tick-able 来模拟服务。我不喜欢改变我的(工作!)代码以适应测试的想法,如果我能提供帮助的话,但我认为我真的需要whenStable 才能工作。除其他外,Angular Material TestbedHarnessEnvironment 在引擎盖下使用它,据我所知,任何包含间隔的组件都不能使用 Material 线束。

我的问题是:截至 2020 年底,我还有更好的选择吗?有没有办法为包含实际间隔的组件或服务编写waitForAsync 风格的测试?或者有没有更好的模式可以用于我的组件设计,也许是一些与现有 Zone.js 测试补丁集成的间隔替换?

【问题讨论】:

【参考方案1】:

我有一个类似(不完全相同)的问题,我解决了如下问题:在测试代码中,在调用 fixture.detectChanges() 之后,我停止了我的计时器(通过取消订阅)。测试代码中唯一的变化是使用公共函数公开取消订阅代码,例如:

stopTimers() 
  this.intervalSubs?.unsubscribe();

然后在你的测试代码中:

component = fixture.componentInstance;
fixture.detectChanges();
component.stopTimers();

【讨论】:

我忘记了这个问题。我从来没有想出更好的解决方案。在某些情况下,我可以通过模拟对使用计时器的服务的依赖来使用whenStable(当然模拟不需要它们),而在其他情况下,我只是避免使用whenStable 并手动依赖@987654326 @-ing,在测试结束时带有discardPeriodicTasks。我从来没有采用TestbedHarnessEnvironment...

以上是关于Angular 组件和服务是不是应该始终避免使用 setInterval(或 rxjs 计时器)?的主要内容,如果未能解决你的问题,请参考以下文章

我应该在注入的 Angular 服务上使用只读而不是公开它们吗?

package.json 中的版本是不是应该始终遵循 semver?

Angular 5服务变量未定义

Ngxs - 调用 Angular 服务:好的做法?

Vue风格指南总结

Angular 1.5/2.0 组件,推荐前缀?