【问题标题】:Angular Change Detection with Observable timer使用 Observable 计时器进行角度变化检测
【发布时间】:2018-11-11 23:36:49
【问题描述】:

背景:

我的 Angular 6 应用程序中有许多组件需要显示当前时间 (hh:mm)。

这些最初是使用setInterval 实现的,this.now 绑定在视图中:

setInterval(() => {
   this.now = new Date();
}, 1000);

自然,这会导致更改检测每秒运行一次,这是一种浪费,因为该值每分钟只会更新一次。我可以通过在ngZone 之外运行setInterval 来改进这一点,并在时间已过时手动触发更改检测。

问题:

我正在尝试实现每分钟发出一个新值的可观察日期流。这就是我目前所做的......

timer(0, 1000)
  .pipe(
    map(() => new Date()),
    distinctUntilChanged((a: Date, b: Date) => a.getMinutes() === b.getMinutes()),
    tap(date => console.log(date))
  );

每分钟发出一次新日期,但是订阅此流会导致 Angular 的更改检测每秒运行一次。 (我通过向订阅的组件添加ngDoCheck 来确认这一点)。

如何推迟更改检测,使其仅在发出新值时发生?

【问题讨论】:

  • 你想做什么?
  • 变更检测通常发生在递归循环中
  • 你试过Observable.interval(1000) 吗?
  • 对不起,如果不清楚:“我正在尝试实现一个可观察的日期流,它每分钟都会发出一个新值。”但是我只希望在发出值时触发更改检测,而不是在计时器触发时每 1000 毫秒触发一次。
  • 在角度区域外运行并设置手动更改值:blog.angularindepth.com/…

标签: angular rxjs observable


【解决方案1】:

您可以为此使用主题和间隔,我想可能是这样的:

基本上在你实现了这个的代码中(假设它是一个单独的服务:some.service.ts),定义一个这样的主题:

someSubject : Subject<Date> = new Subject<Date>();

interval(1000)
  .pipe(
    map(() => new Date()),
    distinctUntilChanged((a: Date, b: Date) => a.getMinutes() === b.getMinutes()),
    tap(date => {
       console.log(date);
       this.someSubject.next(date);
       });
  ).subscribe();

订阅someSubject,无论您想在哪里收听日期变化,如下所示:

this._someService.someSubject.subscribe((date : Date) =>{
 console.log(date); //you'll have a new date object everytime your date object changes i.e everyminute
});

别忘了从rxjs 导入interval

我使用 StackBlitz 创建了一个示例(每秒钟监听一次更改):https://stackblitz.com/edit/angular-4ytdbs

【讨论】:

  • 感谢您的示例,但它仍然每秒触发更改检测。我正在尝试“推迟更改检测,因此它仅在发出新值时发生”。所以每分钟一次,而不是每秒一次。我已经用我所拥有的更新了你的例子:stackblitz.com/edit/angular-jbay8g
  • @MS_AU 它是如何每秒触发一次变更检测的?计时器或间隔会根据您推送的值发出一个 observable
  • Angular 的变更检测是响应异步任务触发的。在timerinterval 的情况下,可观察到的变化检测将在指定的延迟后发生,在我的情况下每秒(1000 毫秒)。鉴于我正在通过 mapdistinctUntilChanged 操作符传递发出的值 - 每分钟只发出一次新值,而不是每秒发出一次。然而,变化检测仍然每秒发生一次。这个问题专门针对使用 Observable 计时器延迟更改检测的最佳实践。
  • @MS_AU 您可以使用 changeDetectionStrategy.detach()changeDetectionStartegy.reattach() 重新附加和分离更改检测,并将 changeDetectionStrategy 设置为 onPush 。我更新了 plunker,但似乎 ngDoCheck 无论如何都被调用了,这不应该是这种情况
猜你喜欢
  • 1970-01-01
  • 2021-06-17
  • 1970-01-01
  • 2021-08-07
  • 2018-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-12
相关资源
最近更新 更多