Search code examples
angularrxjsbehaviorsubjectcombinelatest

RXJS BehaviourSubject emmission order change with combineLatest


In an Angular application, I'm modeling "state" with a BehaviourSubject.

interface State {
  id: number;
  num: number;
  msg: string;
}
private store = new BehaviorSubject<State>(_state);
private state$ = this.store.asObservable();

And I got observables to select the different slices of state:

  msg$ = this.state$.pipe(
   map((state) => state.msg),
   distinctUntilChanged()
  );

  id$ = this.state$.pipe(
   map((state) => state.id),
   distinctUntilChanged()
  );

 num$ = this.state$.pipe(
   map((state) => state.num),
  distinctUntilChanged()
 );

I initialize the state, then update its value using this.store.next with data from an API. Everything is fine until that point.

But I'm also using combineLatest to wait for the emission on two of the observables that slice the state (id and num), to calculate a value for the third one (msg).

So I emmit to the state id and num, and then inside the combineLatest I calculate and emmit to the state a new msg.

The problem is that in the component subscribed to the "msg" observable I receive the correct calculated value, but after I receive the old (the initial) value. Is like combineLatest interrupts the emission in the observables with the correct value, but then the old ones resume and are the latest to be received. Why the order is changing?

I created this example in StackBlizt to check problem.

I expect to have at Message "Data 1 123", but I see the initial value "hi".

Maybe someone knows what it's happening and how to fix it?


Solution

  • This article helped me to find a solution. Putting a debounceTime(0) first thing in the combineLatest it seems put it out of the event loop and allows execution in the expected order. I update also the StackBlizt example with the solution in the case that is useful for someone with a similar problem.