2
votes

Looking at the definition of combineLatest

Combines multiple Observables to create an Observable whose values are calculated from the latest values of each of its input Observables.

or

Whenever any input Observable emits a value, it computes a formula using the latest values from all the inputs, then emits the output of that formula.

enter image description here

It's pretty clear to see that at each period of time / emission , the result at that emission is the combination of the latest emissions.

If so , looking at this code

const obs1 = Rx.Observable.of(1, 2, 3, 4, 5);
const obs2 = Rx.Observable.of('a', 'b', 'c')
const obs3 = obs2.combineLatest(obs1, (a, b) => a+b);

const subscribe = obs3.subscribe(latestValues => {
  console.log(latestValues   );
});

The result is :

c1,c2,c3,c4,c5

And when I change

obs2.combineLatest(obs1..

to

obs1.combineLatest(obs2..

— I get 5a,5b,5c

Question:

The docs don't specify any difference regarding the order of invocation (if so - why do I get different results) ?

Why don't I see other combinations with the other source ? It seems that one source is taking its last value and only then - join it to each value from the OTHER source.

It seems like that this is what actually happening:

[other source]---a---b---c------------------------
[first source]-------------1----2-----3-----4----5
[result]-------------------c1---c2----c3----c4---c5

And when I swap the order (obs1<->obs2) :

[first source]-----1--2---3--4--5----------------
[other source]---------------------a-----b------c
[result]---------------------------5a----5b-----5c

What's going on here? why does one stream has to finish in order for the join to start ?

Why don't I see something like this ( or a variation) :

[first source]-----1-----2--------3-------4------5---
[other source]---------a-----b------c----------------
[result]---------------1a------2b------3b---4c-------5c

JSBIN

1

1 Answers

4
votes

This is because values from your source Observables are emited synchronously unless you use a Scheduler. This means that first obs1 emits all values and only the last one is remembered by combineLatest and than obs2 starts emiting all its values (the same appplies if you switch the two Observables). Now the combineLatest has values for both Observables so any emission from the second Observables will make the operator emit a value.

Why it works like this is because Observable.of is implemented as ArrayObservable internally and by default it doesn't use any Scheduler. This means that all its emissions happen synchronously. See https://github.com/ReactiveX/rxjs/blob/master/src/observable/ArrayObservable.ts#L118

Btw, you can add Rx.Scheduler.async as the last parameter to both source Observables.