Home > other >  Angular debounceTime: Why is not only the last value returned?
Angular debounceTime: Why is not only the last value returned?

Time:11-23

I have a service. This contains the following function (simplified):

private _eventListener$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
push(field?: FormField): void {
    this.isAlive = true;
    this._eventListener$.pipe(
      debounceTime(3500),
      takeWhile(() => this.isAlive)
      ).subscribe(() => {
        this.isAlive = false;
        console.log(field?.control.value)
      });
  }

This function does the following: if a field changes (input, dropdown,...) then the backend should be called and data should be queried. This should not happen directly with every change of a field but only after a certain time nothing has changed. Therefore I have thought, I use debounceTime. But unfortunately this does not work.

If I enter a lot of numbers and I am above the debounce time, all the numbers I enter are logged:

enter image description here

I thought debounceTime always only outputs the last value after nothing has happened for a certain time. Why does this not work?

CodePudding user response:

When something is changed in your component this.formService.push(this.field); is called. This created a new observable (and subscription) on each change. You should just call this function one time (e.g. in your constructor) and only one value will be emitted. Please remember to unsubscribe on destruction or, even better, don't subscribe at all and use an declarative approach using rxjs operators async pipe.

CodePudding user response:

Whenever you call push, you create a new pipeline and subscribe to it. Since the source is a BehaviorSubject a value is emitted immediately upon subscription, which calles the subscribe handler 3.5s later.

To be clear: When you enter 123, push() is called 3 times, you create 3 different and unrelated Observables that you subscribe to. Each of them will wait for 3.5s, then emit the value. However, since all 3 subscribe handlers reference the same field, they output all the same value.


You should build this observable one time, not on each call to push(). And subscribe only once. And in push you only push the next value to a Subject. Example:

private _fieldChanged$ = new Subject<FormField?>();

constructor() {
  this._fieldChanged$.pipe(
    debounceTime(3500)
  ).subscribe((field) => console.log(field?.control.value));
}

push(field?: FormField): void {
  this._fieldChanged$.next(field);
}
  • Related