cancelling a observable with takeUntil not working

Viewed 6263

I have an autocomplete HTTP call and an execute search HTTP call... I need the autocomplete call to abort when the execute action is triggered. What I am doing right now is using a Subject like so:

private onExecute$ = new Subject();

In my autocomplete method:

executeAutoComplete(e) {
  this.myService.searchAutoComplete(e.criteria)
  .pipe(
   takeUntil(this.onDestroy$),
   takeUntil(this.onExecute$),
   map( 
  // continue with more code

Then in my execute method I raise the signal:

executeSearch(e) {
console.log('triggering onExecute signal');
this.onExecute$.next();
  // other code
}

so in my console I see 'triggering onExecute signal' but the autocomplete results return AFTER the full search starts executing, I thought that once I raise the signal the takeUntil will abort the chain? It does not work.

So essentially the behavior I am trying to prevent is that the autocomplete results should not return and open the drop down when a search is triggered by the user since it's no longer relevant.

What am I missing here?

Edit -

the order is infact the issue due to the debounce time the execute is always called before autocomplete, order can be unpredictable anways. Did not realize that the onExecute.next() will be lost if the Observable chain is not yet active.

I do have a searchLoading variable that is also set, how can I use this?

I tried:

takeUntil(Observable.of(this.searchLoading))

This does not work as it's always true! how do I use takeUntil with a boolean value that is evaluated dynamically?

Edit 2 -

Got it using takeWhile instead:

takeWhile(() => !this.searchLoading))
4 Answers

It is old but i had the same cenario.

If you want to use takeUntil, the correct Subject is ReplaySubject.

  • Because if Subject emits anything before takeUntil call, it will not reemit when takeUntil subscribes to Subject(as implementation do), and takeUntil will not unsubscribe the source.
  • On the other way, ReplaySubject reemits on subscription, so takeUntil will cancel with it internal unsubscribe call.

In my case the problem was in this.destroy$.complete(); I was using subscription in service which was invoked in many components. And I was trying to to stop the subscription in service from component OnDestroy hook by calling service method:

destroySubscriptions() {
    this.destroy$.next();
    this.destroy$.complete();
}

But after the first component has stop the subscription and complete destroy$ Subject, the next component cannot stop the subscription in service because the destroy$ Subject was already completed and the this.destroy$.next(); do not take any actions. So be careful by completing the Subject, it will not work any more. Such an ambiguous stuff : )

Related