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)
.
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.
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.