Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Is there a way to indicate when the RxJS operator "switchMap" discards a previous emitted item by the source Observable?

I am using an "in progress" indicator that is displayed as long as tasks are currently running.
When starting a task, the tasks counter increases by 1 and decreases by 1 at the end of the task.
Basically: if (count>0) displayIndicator().

When a new inner Observable is emitted, switchMap stops emitting items from the earlier-emitted inner Observable and begins emitting items from the new one.

The problem is, that disregarding earlier-emmited Observables does not trigger the counter that decreases this.uiService.indicator.task(-1).

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

init(): void {
    this.searchResults$: Observable<SearchResult[]> = this.searchTerms.pipe(

    // wait 700ms after each keystroke before considering the term
    debounceTime(700),

    // ignore new term if same as previous term
    distinctUntilChanged(),
      
    // switch to new search observable each time the term changes and discard previous (active) responses
    switchMap((searchTerm, i) => this.apiService.searchDB(searchTerm, i))
    );


    this.searchSubscription = this.searchResults$.subscribe({
      next: (response) => {
        console.log('received', response)
        this.uiService.indicator.task(-1);
      }
}
triggerSearch(term: string): void {
    this.searchTerms.next(term);
}
apiService.searchDB(searchTerm, i): Observable<SearchResult[]> {
    this.uiService.indicator.task(+1);
    ...
}

I’ve tried using the tap operator to catch it after switchMap, but it’s not being triggered either since switchMap interrupts passing Observables when a new searchTerm is emitted.

>Solution :

Try using the finalize operator inside the switchMap:


switchMap((searchTerm, i) => this.apiService.searchDB(searchTerm, i)).pipe(
  finalize(() => this.uiService.indicator.task(-1)
)

...

this.searchSubscription = this.searchResults$.subscribe((response) => console.log('received', response));

Untested as I’m on mobile.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading