Thabo
Thabo

Reputation: 1465

Rxjs: Wait for outer observable, pass value to inner and return both resolved values in subscription

I have tried a few operators to achieve a usecase. I would like to perform a HTTP request, and when this outer observable is resolved, I would like to use it's value to perform another one and after combine both the resolved values to one observable of the outer and inner observable.

I am not sure how and which operators or a combination I can use.

I have tried the below.

import { forkJoin, interval, of } from "rxjs";
import { map, mergeMap, take, tap } from "rxjs/operators";


of('outer')
.pipe(
  map(
    (v) => {
      console.log(`${v}===> inner`);

      return forkJoin([
        of(`${v}===> inner`),
        of(v)
      ])
    }
  )
  ,
  tap(
    (v) => {
      console.log('tap', v);
    }
  )
 
)
.subscribe(
  (v) => {
    console.log('sub', v)
  }
)

Upvotes: 0

Views: 318

Answers (2)

Pawel Kiszka
Pawel Kiszka

Reputation: 850

Something like this should do the work

of('outer').pipe(
  switchMap(outerResult => of('inner').pipe(
    tap(innerResult => console.log('outer', outerResult, 'inner', innerResult),
      map(innerResult => ({
          inner: innerResult,
          outer: outerResult
        })
      )
    )))).subscribe(
       result => {
         console.log(result);
         // the result should be an object with `inner` and `outer` keys
       }
)

  • once outer is resolved, then you switch to inner
  • because you are still inside switchMap, you can access outerResult in tap operator

Upvotes: 1

Thabo
Thabo

Reputation: 1465

I have achieved what I wanted but not sure if this is the best way to do it.

I have used the combineAll operator.

Could this be the best way to do or there is a more intuitive way or maybe use fewer operators?

import { forkJoin, interval, of } from "rxjs";
import { combineAll, map, mergeMap, take, tap } from "rxjs/operators";

    of('outer')
    .pipe(
      map(
        (v) => {
          console.log(`${v}===> inner`);
          return forkJoin([
            of(`${v}===> inner`),
            of(v)
          ])
        }
      ),
      combineAll()
      ,
      tap(
        (v) => {
          console.log('tap', v);
        }
      )
     
    )
    .subscribe(
      (v) => {
        console.log('sub', v)
      }
    )

UPDATE:

Another way for a cleaner value was to follow the suggestion above but with a bit of tweak.

But still combineAll makes it work

of('outer').pipe(
  switchMap(outerResult => of('inner').pipe(
     map((innerResult) =>  {
      return of({outerResult, innerResult});
     })
    )
  ),
  combineAll()
)
  .subscribe(
    (v) => {
      console.log(v);
    }
  );

Final:

The solution by Pawel above was really helpful. The updated code without errors is below.

of('outer').pipe(
  switchMap(outerResult => of(`${outerResult} ==> inner`).pipe(
    tap(
      (inner) => {
        console.log('tap', inner);
      }
    ),
     map(innerResult => ({
       inner: innerResult,
       outer: outerResult
      })
    )
  ))
).subscribe(
  (v) => {
    console.log(v);
  }
)

Upvotes: 0

Related Questions