如何在OnPush组件(stackblitz)中消除时间抖动



我正在学习RXJS,并有以下上下文:

服务:

import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable, interval } from 'rxjs';
import { debounceTime, tap, debounce } from 'rxjs/operators';

@Injectable({ providedIn: 'root' })
export class SomeProvider {
private counter: BehaviorSubject<number> = new BehaviorSubject(0);
public counter$ = this.counter.asObservable() // .pipe(debounceTime(2000))
constructor(
) {
interval(1000).subscribe(value => {
console.log(value);
this.counter.next(value);
})
};
}

组件:

import { Component, ChangeDetectionStrategy } from '@angular/core';
import { SomeProvider } from './some.service';
@Component({
selector: 'hello',
template: `<h1>{{ provider.counter$ | async }}</h1>`,
styles: [`h1 { font-family: Lato; }`],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class HelloComponent  {
constructor(public provider: SomeProvider) {
}
}

这是堆叠litz:https://stackblitz.com/edit/angular-ivy-cdvwnj

所以问题是,现在组件每秒都会更新组件模板中的计数器。我想简单地使用debounceTime来取消它。我认为这将像使用debounceTime操作符向Observable添加管道一样简单。但是,如果我取消注释,那么更改计数器甚至不存在。

问题:

  • 如何在这种情况下正确应用debounceTime
  • 为什么我们在模板内添加带有debounceTime的管道异步管道会停止工作(并且需要额外的更改检测(

与其重写docs中已经编写的内容,不如尝试用简单的外行语言来理解

debounceTime((-它是一个RxJs运算符,在给定的时间限制内侦听的所有传入数据流,并且只转发最后一个

示例:-

MyAwesomeObservable().pipe(debounceTime(10000))

这意味着去抖动时间将不会转发数据流,直到10秒过去。在这10秒期间,如果有新的数据流到来,debounceTime将再次开始等待10秒。

您的案例:-

由于interval(1000)每1秒传递一次数据,因此debounceTime(2000)等待2秒的时间永远不会结束。

间隔>debouncetime,则您的代码将正常工作。

来自文档

只有在经过特定时间跨度后才从源Observable发射值,而没有其他源发射

如果传递到debounceTime<传递给interval的时间

演示

与前面提到的其他答案一样,因为您的debounceTime高于interval(),它将导致所有间隔排放都被"去抖动"。

如果你想取消一个间隔的抖动,使其每2秒而不是1秒发射一次,并且你无法控制间隔时间,你可以使用一个过滤器:

public counter$ = this.counter.asObservable().pipe(
filter((idx) => !(idx % 2))
)

这将使您的计数器仅以均匀的排放量进行排放。

参见此处

最新更新