Hot, cold, and warm Observables

There are hot, cold, and warm Observables. What do we actually mean by that? For starters, let's say that most things you will deal with are cold Observables. Not helping? If we say that cold Observables are lazy, does that help? No? OK, let's talk about Promises for a second. Promises are hot. They are hot because when we execute their code, it happens straight away. Let's see an example of that:

// hot-cold-warm/promise.js

function getData() {
return new Promise(resolve => {
console.log("this will be printed straight away");
setTimeout(() => resolve("some data"), 3000);
});
}

// emits 'some data' after 3 seconds
getData().then(data => console.log("3 seconds later", data));

If you come from a non-RxJS background, you will most likely, at this point, think: OK, yes, that's what I expected. This is the point we are trying to make, though: Calling getData() makes your code run straight away. This differs from RxJS in the sense that similar RxJS code will actually not run until there is a listener/subscriber that cares about the result. RxJS answers the old philosophical question: Does a tree make a sound when it falls in the forest if no one is there to listen? In the case of Promises, it does. In the case of an Observable, it doesn't. Let's clarify what we just said with a similar code example using RxJS and Observables:

// hot-cold-warm/observer.js

const Rx = require("rxjs/Rx");

function getData() {
return Rx.Observable(observer => {
console.log("this won't be printed until a subscriber exists");
setTimeout(() => {
observer.next("some data");
observer.complete();
}, 3000);
});
}

// nothing happens
getData();

In RxJS, code like this is considered cold, or lazy. We need a subscriber for something to actually happen. We can add a subscriber like so:

// hot-cold-warm/observer-with-subscriber

const Rx = require("rxjs/Rx");

function getData() {
return Rx.Observable.create(observer => {
console.log("this won't be printed until a subscriber exists");

setTimeout(() => {
observer.next("some data");
observer.complete();
}, 3000);
});
}

const stream$ = getData();
stream$.subscribe(data => console.log("data from observer", data));

This is a major difference in how Observables behave versus Promises, and it's important to know. This is a cold Observable; so, what is a hot Observable? It would be easy to think, at this point, that a hot Observable is something that executes straight away; there is more to it than that, however. One of the official explanations of what a hot Observable is, is that anything that subscribes to it will share the Producer with other Subscribers. The Producer is what spouts out values internally inside the Observable. This means that the data is shared. Let's look at a cold Observable subscription scenario and contrast that with a hot Observable subscription scenario. We will start with the cold scenario:

// hot-cold-warm/cold-observable.js
const Rx = require("rxjs/Rx");

const stream$ = Rx.Observable.interval(1000).take(3);

// subscriber 1 emits 0, 1, 2
stream$.subscribe(data => console.log(data));

// subscriber 2, emits 0, 1, 2
stream$.subscribe(data => console.log(data));

// subscriber 3, emits 0, 1, 2, after 2 seconds
setTimeout(() => {
stream$.subscribe(data => console.log(data));
}, 3000);

In the preceding code, we have three different subscribers that receive their own copy of emitted values. The values start from the beginning, every time we add a new subscriber. That might be expected when looking at the two first subscribers. As for the third one, it is added as a subscriber after two seconds. Yes, even that subscriber receives its own set of values. The explanation is that each subscriber receives its own Producer upon subscription. 

With hot Observables, there is just one producer, which means the scenario above will play out differently. Let's write down the code for a hot Observable scenario:

// hot observable scenario

// subscriber 1 emits 0, 1, 2
hotStream$.subscribe(data => console.log(data));

// subscriber 2, emits 0, 1, 2
hotStream$.subscribe(data => console.log(data));

// subscriber 3, emits 2, after 2 seconds
setTimeout(() => {
hotStream$.subscribe(data => console.log(data));
}, 3000);

The reason the third subscriber is outputting only the value 2 is that the other values have been emitted already. The third subscriber wasn't around to see that happen. On the third value emit, it is around, and that is the reason it receives the value 2.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset