Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to finish an active debounceTime in OnDestroy

Tags:

angular

rxjs

I am currently saving values when a user changes an input field. I don't want to save the value each time a new character is entered so I'm using the rxjs debounceTime to save after 3000ms (just an example) of no changes.

this.subscription.add(this.form.controls.inputControl.valueChanges
        .pipe(debounceTime(3000))
        .subscribe(value => {
            // execute HTTP call with value
        }));

ngOnDestroy(): void {
    this.subscription.unsubscribe();
}

If the user changes the value and OnDestroy gets called before the 3000ms timer is reached, the call won't get executed no more. I was wondering if there was a way to cancel the active timer and execute all remaining observables before destroying the component.

EDIT: Another option could be that the user gets a warning when there are unsaved changes. Like the way google calendar does when adding a new task and leaving the page

like image 686
RDNotorious Avatar asked Nov 06 '25 04:11

RDNotorious


1 Answers

const destroyed = new Subject();
const isTimerActive = new BehaviorSubject(false);

const stop$ = combineLatest(destroyed, isTimerActive)
  .pipe(
    filter(([isDestroyed, isTimerActive]) => isDestroyed && !isTimerActive)
  );

src$.pipe(
  debounce(
    () => (
      // Now if the component is destroyed, it will not unsubscribe from this stream
      isTimerActive.next(true),
      timer(/* ... */)
    )
  ),
  switchMap(v => makeRequest(v)),

  // If the component is destroyed, then after sending this
  // the stream will be unsubscribed
  tap(() => isTimerActive.next(false)),

  takeUntil(stop$)
).subscribe(/* ... */)


ngOnDestroy () {
  this.destroyed.next(true);
  this.destroyed.complete();
}

It's important to note that the timer is declared inactive(isTimerActive.next(false)) only when we've finished all the tasks that involve the value emitted after the delay.

This is because if destroyed is true and we immediately do isTimerActive.next(false), the unsubscription will happen synchronously, meaning that you won't be able to do anything else with that value.

like image 73
Andrei Gătej Avatar answered Nov 08 '25 09:11

Andrei Gătej



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!