带有可观察计时器的角度变化检测

时间:2018-11-11 23:36:49

标签: angular rxjs observable

背景

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

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

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

自然,这会使更改检测每秒钟运行一次,这很浪费,因为该值每分钟仅更新一次。我可以通过在setInterval之外运行ngZone并在分钟过去了时手动触发变更检测来改善这一点。

问题:

我正在尝试实现一个可观察的日期流,该日期流每分钟都会发出一个新值。这是我到目前为止所要做的...

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

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

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

1 个答案:

答案 0 :(得分:0)

您可以为此使用主题和间隔:

基本上在您实现此代码的代码中(假设它是一项单独的服务: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
});

不要忘记从interval导入rxjs

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