RobertAKARobin
RobertAKARobin

Reputation: 4258

Why is the `merge` operator completing before the source observables have completed?

I have two source observables, and want to do something when either emits a value, regardless of whether they’re completed:

const observable1$ = interval(1000);
const observable2$ = interval(2000);
const onEither$ = merge([
  observable1$,
  observable2$,
]);

observable1$.pipe(tap(() => console.log('observable1 emit')), finalize(() => console.log('observable1 complete'))).subscribe();
observable2$.pipe(tap(() => console.log('observable2 emit')), finalize(() => console.log('observable2 complete'))).subscribe();
onEither$.pipe(tap(() => console.log('onEither emit')), finalize(() => console.log('onEither complete'))).subscribe();

What I’m seeing is:

onEither emit
onEither complete
observable1 emit
observable2 emit
...(observable1 and 2 repeat)

My understanding is merge only completes when all source observables have completed. So why is onEither completing?

Upvotes: 1

Views: 278

Answers (1)

Poul Kruijt
Poul Kruijt

Reputation: 71891

It's because you are passing an array into merge. It's supposed to be a list of parameters. Change to:

const onEither$ = merge(
  observable1$,
  observable2$,
);

The reason it completes, is because internally rxjs calls the from method, which converts the array into an observable stream of the array elements. So basically your onEither$ is receiving two emits, which have the value of both observable objects in the array. After those have been emitted, the observable completes.

The observables in the array are untouched, because they are just used as a value, and not actually subscribed to

Upvotes: 3

Related Questions