In the category of combination operators, concat executes Observables sequentially, while merge executes them in parallel. This lesson will teach you how the merge operator is an OR-style combination operator that blends two or more Observables together.
🚨 Since we are importing interval
from RxJS, we don't need to preface our Observables with Rx.Observable
. You can no longer .{operator}
, you need to .pipe({operator})
instead.
[00:01] The concat operator is a combination operator. It combines two or more observables sequentially. For instance, here we had "foo." We combined it with "more" sequentially to produce this output observable that first delivers values from foo and then delivers values from more.
[00:17] There are other combination operators which work in a different fashion. Suppose we have these two observables, "foo" and "bar," both of them created with interval. Foo ticks every 500 milliseconds. Bar ticks every 300 milliseconds.
[00:32] We want to combine them together not sequentially but in parallel. That means that the output observable that we will see at the bottom will deliver values from either foo or bar. That happens in parallel. In practice, this operator that we're going to use is going to subscribe to both of them at the same time. It will deliver the values that come from either one of them.
[00:57] Bar delivered one value here. That's going to come out in the output observable. But also foo delivered a value. We're going to deliver that. Zero from foo. Then we're going to deliver one from bar, two from bar, one from foo, three.
[01:13] Then you see here two being delivered at the same time as four and complete from bar. This means that we're going to have two and four being delivered sequentially and synchronously in the same event loop. You can see that bar completed.
[01:31] But we're not actually going to complete the output observable. That's because, since we're running these two in parallel, we still have values that will be delivered from foo. That's why we are able to continue.
[01:44] Once we get three and completion from foo, we can complete the output observable because we know that of course if you're just delivering values from both of these, and both of these have completed, then you know that the output observable can't really deliver anything else. That's why we're able to complete.
[02:03] We just want to blend these two observables together. The name of the operator for this is called merge. It really allows you to do just that. It allows you to merge together these two observables by running them in parallel and blending their delivered values. You use it in an API similar to concat.
[02:25] We do foo.merge, so that's an instance operator with bar. Then you can get this merged observable which executes like this ones we subscribed, so delivers zero, zero, one, two, one, three, two, four, three, done, just like we saw here in our marble diagram.
[02:44] Also, merge has a static operator version, just like concat had -- had Rx.Observable.merge foo with bar together. It does the same thing as before. That's why you would use merge, is to deliver values from either one of these member observables.
[03:05] I like to call merge the "or operator" in RxJS because values being delivered on the output observable come from either foo observable or bar observable. Then you can really see the "or" logic happening there. You can also see it happening in practice.
[03:23] Let's say this would be all the clicks happening on your app. You know that all of the clicks can either come from clicks on the button or clicks on the page. You can really see there the logic happening because you know that all of the clicks are from this, or from that, or from this, or from that.
[03:50] In general, that's how you should reason about the merge operator. It blends everything in an or style.
Hi Klemen. Yes that is to some extent correct, but it depends on the underlying scheduler. Schedulers are a concept we don't cover in this course, but in a nutshell they allow you to choose what is "time" and how to run things with time. Here, the Observable.interval() would schedule emissions with a setInterval, and that's why 2 and 4 would not be emitted synchronously. However, if we used the VirtualTimeScheduler, it would just simulate a setInterval, and essentially then it is able to accomplish emissions of 2 and 4 at the "same time" (under its own concept of time).
What matters here is that each character in the ascii marble diagram stands for one "time unit", and what the original diagram meant is that 2 and 4 occur "in the same time unit". --24-
isn't correct either because 4 does not occur "one time unit" (in our case, 100ms) ahead of 2.
Ah, OK, that makes sense. Thank you!
Wouldn't the marble diagram for the example given look like this?
The
(24)
wouldn't happen synchronously, just very closely together.