0

I'm still new to rxjs, so I'm having trouble on how to do this. I want to perform a side effect when all the observables from my mergeMap completes, but I don't know how to "split" the original stream into a new one.

It looks like from here Wait for all observables in mergeMap to complete before emitting a custom value that I can use ignoreElements and endsWith(undefined) but I'd like to keep the original observables from the mergeMap alive

e.g.

action$.pipe(
filter(..),
mergeMap(action => nextAction(action)),
performSideEffectWhenMergeMapDone()

How do I do this?

I've also tried something like this:


  const next = action$.pipe(
    filter(..),
    mergeMap(...))

  next.pipe(
    ignoreElements(),
    endWith(undefined),
    tap(() => {...}
    })
  );
  return next

but the tap() never gets hit since the second epic is never registered

Dennis
  • 21
  • 6

2 Answers2

0

If I understand your issue correctly all this is a part of Redux action? endWith() won't help you in this case because endWith() will only emit when its source Observable completes but Redux source of actions never completes.

What exactly you should do depends on what nextAction is. If it returns an Observable that completes you could do it like this:

action$.pipe(
filter(..),
mergeMap(action => nextAction(action).pipe(
  tap({
    complete: () => performSideEffectWhenMergeMapDone()
  }),
)),

In other words, you'll wait for the inner Observble in mergeMap to complete, not the outer Observable where mergeMap is used.

martin
  • 93,354
  • 25
  • 191
  • 226
  • Ah, okay. This makes sense. This is indeed part of a redux action. Moving the tap inside worked, but also isn't quite what i'm looking for. nextAction in this case is also a `mergeMap` eg `doSomething(action).expand(..).mergeMap(..)` so tap complete is triggering on action – Dennis Nov 10 '21 at 14:01
  • **Side Note:** `const fn = () => gn()` is the same as just `const fn = gn`. The two are semantically identical. Though actually the first might be slightly slower because it's two function calls instead of one. They will always produce the same results. – Mrk Sef Nov 10 '21 at 14:15
-1

Just like subscribe, tap and can take an observer(or a partial observer).

An observerhas this shape:

{
  next: v => {...},
  error: e => {...},
  complete: () => {...}
}

In this case, a partial observer that implements complete is enough:

action$.pipe(
  filter(..),
  mergeMap(action => nextAction(action)),
  tap({
    complete: performSideEffectWhenMergeMapDone
  })
);
Mrk Sef
  • 7,557
  • 1
  • 9
  • 21