Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

switchMap and debounceTime cancel pending

I have a method that will search for employee's based on a search term.

this._sub.pipe(
    debounceTime(500),
    filter(x => !!x),
    distinctUntilChanged(),
    switchMap(this.getResults.bind(this))
).subscribe((d: IDisplayEmp[]) => {
    console.log('RES', d)
    this.displayResults = d;
});

this._sub.next('mySearchTerm');

This works great, previous API calls are cancelled if a new one is issued. However here comes the issue.

Active API calls are only cancelled when the debounce has emitted. If an active API call returns whilst the debounce is waiting it still triggers my subscribe.

I understand this is because the cancelling only happens within the scope of the switchmap.

Is possible to refactor this so that if the debounce is waiting for input to stop it will cancel any pending API calls?

Probably a naive approach but i attempted something like below, it emits values but now there is no debounce in effect.

this._sub.pipe(
    filter(x => !!x),
    distinctUntilChanged(),
    switchMap((x) => {
        return of(x)
            .pipe(
                debounceTime(500),
                this.getResults.bind(this)
            );
    })
).subscribe((d: IDisplayEmp[]) => {
    console.log('RES', d)
    this.displayResults = d;
});

Thanks for any help.

like image 553
ste2425 Avatar asked Jun 07 '26 01:06

ste2425


2 Answers

Use takeUntil to cancel your requests whenever this._sub emits.

this._sub.pipe(
    debounceTime(500),
    filter(x => !!x),
    distinctUntilChanged(),
    switchMap(searchTerm => this.getResults(searchTerm).pipe(
      takeUntil(this._sub)
    ))
).subscribe((d: IDisplayEmp[]) => {
    console.log('RES', d)
    this.displayResults = d;
});
like image 198
frido Avatar answered Jun 10 '26 06:06

frido


The accepted answer should work fine, but I wanted to share another way you can do this with timer instead of debounceTime:

this._sub.pipe(
    filter(x => !!x),
    distinctUntilChanged(),
    switchMap(val => timer(500).pipe(
        switchMap(() => this.getResults(val))
    ))
).subscribe(...);

Now, if an emissions reaches switchMap, the timer and everything in it (including an active network request) will be canceled, and a new timer will be created.

like image 35
Christian Jensen Avatar answered Jun 10 '26 07:06

Christian Jensen



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!