How to take action when multiple RxJS forkjoins are complete?

Viewed 154

I have two separate Rxjs forkjoins. We always run the first one and the second one might run conditionally. But we need to take an action when both are complete or when the first one is complete (if the second one is not called).

How can I achieved it?

sub1 = forkjoin([item1, item2])

sub2 = forkjoin([item3, item4])
3 Answers

You have 2 observables that you want to trigger at the same time. Simplest way is to merge them and concat with the action you want to take at the end:

const action1$ = forkjoin([item1, item2]);
const action2$ = forkjoin([item3, item4]);

concat([
  merge([action1$, action2$]),
  defer(() => {
    // this will happen after action1 and action2 are complete
    return EMPTY;
  }),
]);

You could use an outer forkJoin with iif to conditionally trigger the second observable. And pipe in finalize to perform some action on completion.

forkJoin(
  forkjoin([item1, item2]),
  iif(
    () => someCondition,
    forkjoin([item3, item4])
  )
).pipe(
  finalize(() => {
    // do something when the source observables complete
  )
)

Assuming that the second forkJoin gets triggered based on a condition depending on the result returned by the first forkJoin, I would proceed like this

forkjoin([item1, item2]).pipe(
   // use concatMap to trigger a second Observable once the firs one has emitted
   concatMap(resultOfFirst => {
      // check somehow whether the condition is met
      return isConditionMetToTriggerSecond(resultOfFirst) ? 
         forkjoin([item1, item2]).pipe(
            // use map to return both the first and the second result
            map(resultOfSecond => {
               return [resultOfFirst, resultOfSecond]
            })
         ) :
         // if the condition is not met return just the first result
         of([resultOfFirst, null])
   })
).subscribe(
   // take an action when either the first or both complete
   ([resultOfFirst, resultOfSecond]) => {
      // do something if both have been executed
      if(!!resultOfSecond) {
         // do stuff with both results
      }
   } else {  // do something if only the first has been executed
        // do stuff with first result
   }
)
Related