Diesel
Diesel

Reputation: 5335

Stopping outer observable with switchmap without completing inner observables

I've searched for a similar question but couldn't find one that matches, so apologies if this is a duplicate.

I have several chained observables.

Observable A calls Observable B via switchmap.

Now Observable B is actually a Behavior Subject, but that I don't think is relevant to the question.

Now observable B never completes. It constantly passes either true or false.

Observable B calls Observable C via a switchmap when it receives a value of true. Observable C does things and calls other observables via switchmap. So on and so on.

What I need to happen is when observable B receives false, it does nothing (currently setup that way). When observable B receives true, it calls observable C (currently works). Now it propagates through to my original subscription and I'm good to go with the result from my last observable.

But...... it never completes because Observable B never completes. How do I make observable B complete or unsubscribe from it without stopping the chain after it from happening? So when Observable B gets a .next(true) again, it fires the chain again, not what I want.

I attempted using takeUntil which I passed an observable that fired when a true was received. The problem with takeUntil is everything immediately completed and my subscription never receives a value (Observable C and on never fire).

Here is some code with logic removed.

private initMap(): Observable<boolean> {
      return this.platformHelperService.getUserLocation().pipe(
        switchMap(_ => {
         return this.updateMapCenterLocation();

public updateMapCenterLocation(): Observable<boolean> {
    let mapCenterSetObserver: Observer<void>;
    const mapCenterSetObsersable = Observable.create(
      (observer: Observer<void>) => {
        mapCenterSetObserver = observer;
      }
    );

    // This is observable B
    return this.mapAssignedBehaviorSubject.pipe(
        switchMap(assigned => {
        if (assigned) {
          // Observable C below. Later my subscription does more after this completes
          return this.platformHelperService.getUserLocation()
          // If I run below my initial subscription finishes right away and C never runs.
          // If I don't run this, subscription B never completes.
          mapCenterSetObserver.next(undefined);
          mapCenterSetObserver.complete();
        }
   }),
   takeUntil(mapCenterSetObsersable)
   );
  }

Upvotes: 0

Views: 1931

Answers (1)

Fan Cheung
Fan Cheung

Reputation: 11345

Let true pass through one time in observable B might work.

.... 
ObservableA.pipe(
switchMap(()=>observableB.pipe(filter(res=>res),take(1))
switchMap(()=>ObservableC())
)

Upvotes: 3

Related Questions