Home > Back-end >  Wait observable inside another observable
Wait observable inside another observable

Time:07-27

I'm having a problem where I'm returning an observable and sometimes inside that observable I should get a value from another observable. I simplified my problem to much simpler case but main problem is still there. Consider following code that works:

    public dummyStream(): Observable<number> {
    return of(true).pipe(
      switchMap(isTrue =>
        iif(() => isTrue === true,
          combineLatest([of([1,2,3,4,5]), of(2)]).pipe(
            map(([arrayOfNumbers, multiplier]) => {
              const results = arrayOfNumbers.map(num => {
                if (num !== 5) return num;
                else return 4;
              });
      
              return results.reduce((prev, curr) => prev   curr, 0);
            })
          ),
          
          combineLatest([of([1,2,3,4,5]), of(2)]).pipe(
            map(([arrayOfNumbers, multiplier]) => {
              return 0;
            })
          )
        )
      )
    );
  }

So little explanation. It all starts with of(true). For simplicity in this example it's always true so once we get to iif() condition is always true.

Inside there I have combineLatest that combines two observables. Then eventually I do arrayOfNumbers.map and simply return that number again except in a case where number is 5 then I return 4.

Now what I'd like to do is to return of(num * multiplier) but then of course return type from map would by either number or Observable<number> and that's not working.

So this is same code but instead of returning number I'm returning Observable<number> in else block

    public dummyStream(): Observable<number> {
    return of(true).pipe(
      switchMap(isTrue =>
        iif(() => isTrue === true,
          combineLatest([of([1,2,3,4,5]), of(2)]).pipe(
            map(([arrayOfNumbers, multiplier]) => {
              const results = arrayOfNumbers.map(num => {
                if (num !== 5) return num;
                else of(num * multiplier);
              });
      
              return results.reduce((prev, curr) => prev   curr, 0);
            })
          ),
          
          combineLatest([of([1,2,3,4,5]), of(2)]).pipe(
            map(([arrayOfNumbers, multiplier]) => {
              return 0;
            })
          )
        )
      )
    );
  }

Now how should I change this so that dummyStream() return type would still be Observable<number> but so that inside my else block I'm using another observable?

CodePudding user response:

I would restructure dummyStream like this:

function dummyStream() {
    return of(true).pipe(
      switchMap(isTrue =>
        iif(() => isTrue === true,
          combineLatest([of([1,2,3,4,5]), of(2)]).pipe(
            switchMap(([arrayOfNumbers, multiplier]) => {
              return forkJoin(arrayOfNumbers.map(num => {
                if (num !== 5) return of(num);
                else return of(num * multiplier);
              }));
            }),
            map((results) => results.reduce((prev, curr) => prev   curr, 0))
          ),
          
          combineLatest([of([1,2,3,4,5]), of(2)]).pipe(
            map(([arrayOfNumbers, multiplier]) => {
              return 0;
            })
          )
        )
      )
    );
}

So instead of just return num in the map, you return of(num) so that you end up with an array of Observable<number>. Change the outer map to a switchMap and wrap the resulting array in a forkJoin to wait for all inner observables to finish. You can put the reduce in its own map afterwards.

Playground

  • Related