While answering a question I actually came across the thought of whether the order of a merged observable is guaranteed if the input observables emit synchronously. Consider this example:
Observable.merge(Observable.of(1), Observable.of(2))
.subscribe(console.log);
Is this guaranteed to emit 1 and then 2 or could it also be the other way around? I'm not so much asking about the current implementation but about the contract the merge operator gives me.
Whatever the answer, it should probably be documented. The current docs don't seem to mention the order at all.
There's actually a test which seems to verify the order stability:
it('should merge parallel emissions', function () {
var e1 = hot('---a----b----c----|');
var e1subs = '^ !';
var e2 = hot('---x----y----z----|');
var e2subs = '^ !';
var expected = '---(ax)-(by)-(cz)-|';
var result = Observable.merge(e1, e2);
expectObservable(result).toBe(expected);
expectSubscriptions(e1.subscriptions).toBe(e1subs);
expectSubscriptions(e2.subscriptions).toBe(e2subs);
});
As I said, I guess this should be documented.
You can use concat if you need to things to execute in order.
But concat concatenates the entire sequences, perhaps the example was not good enough. Consider this instead:
Observable.merge(
Observable.interval(1000).startWith(1),
Observable.interval(1000).startWith(2),
)
.subscribe(console.log);
Here, using concat is not an option and the question remains the same whether the synchronously emitted values are in order or not. Although as pointed out above the tests already verify order, so it's just a matter of documentation.
@Airblader My understanding of the guarantee is that the observables will be subscribed to in the order in which they are passed.
With your example:
Observable.merge(
Observable.interval(1000).startWith(1),
Observable.interval(1000).startWith(2),
)
.subscribe(console.log);
1 will be received and merged upon subscription to the first observable and 2 will be received and merged upon subscription to the second.
There is no guarantee that the timer-emitted values from the first and second observables will be received in that order.
The test you referenced can rely upon seemingly similar behaviour because the VirtualTimeScheduler (and the TestScheduler that's based upon it) is deterministic.
There is no guarantee that the timer-emitted values from the first and second observables will be received in that order.
Yes, that's fine. I'm only talking about the synchronous emissions. The timers were just there to show that "use concat instead" isn't an answer. :-)
This seems like the behavior of the recursive scheduler. Can you read https://staltz.com/primer-on-rxjs-schedulers.html and see if that answers most of your concerns?
@staltz It does, yes, thanks. My concern was actually the documentation. I'm not extremely happy with the fact that a user would have to dig into schedulers to find out whether the order in this case is guaranteed or not, though.
the order of subscription is gauranteed. The order of events coming out would depend on what you're subscribing to, It's just raw function calls out of the back.
Closing in favor of an issue on the docs repository: https://github.com/ReactiveX/rxjs-docs/issues/241
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment
This seems like the behavior of the recursive scheduler. Can you read https://staltz.com/primer-on-rxjs-schedulers.html and see if that answers most of your concerns?