Hot vs Cold Observables
I mentioned subscribing to an observable a couple of times now, but what does that actually mean? To be notified when a new value is emitted from an observable, we need to subscribe to it. Subscribing tells the observable, “Hey, I want to know about all the values that appear on this stream.” They need to be observed. Observables by themselves, won’t actually do anything. Until they are subscribed to, all you’ve done is describe the series of transformations you want to be done to data on the stream.
It’s sort of like that question, “If a tree falls in the woods, and no-one is around to hear it, does it make a sound?”
In the case of observables, the answer is no!
An observable’s that have no-one around to hear them are called cold
observables.
Put simply: Cold Observables don’t do anything until they are subscribed to, or observed.
In fact, each subscription to a cold
observable, get’s their own, independent stream of ALL items emitted; their own independent execution.
That fact is an important one. Consider this example:
const sample = Observable.interval(1000).map(x => x + 1).take(10);
sample.subscribe(x => console.log(`A: ${x}`));
setTimeout(() => {
sample.subscribe(x => console.log(` B: ${x}`));
}, 4500);
What would happen here? Well, let’s break it down line by line.
const sample = Observable.interval(1000).map(x => x + 1).take(10);
Here we are creating an observable that will emit an incremental number every 1 second, add 1 to that value, and quit after the first ten values. So it will emit 1 through 10 over the course of ten seconds.
sample.subscribe(x => console.log(
A: ${x}));
Our sample observable doesn’t actually do anything until we subscribe to it. Here we are subscribing to it, and logging out every value emitted. It will log to console: A: 1
, A: 2
, A: 3
, and so on each second until A: 10
is reached.
setTimeout(() => {
sample.subscribe(x => console.log(` B: ${x}`));
}, 4500);
This is where it gets tricky. We are again subscribing to our sample observable, but after 4.5 seconds have passed.
What will happen? You may think that this subscription will start at B: 5
, and continue logging until B: 10
. You would be wrong. After 4.5s, it will start logging B: 1
, B: 2
, B: 3
, and so on until B: 10
is reached.
This is what is meant by a cold
observable. The observable doesn’t do anything until it is subscribed to, and each subscription get’s their own independent stream of values from the beginning. Most observables you deal with will be cold
observables.
Okay, so what if we wanted the other behavior. What if we wanted the observable to only start us off from now and ignore everything that happened before.
This is what is referred to as a hot
observable. A cold observable can be made into a hot observable using the share
operator. Let’s look at our example again.
const sample = Observable.interval(1000).map(x => x + 1).take(10);
We know this is a cold
observable from before. Try Me
Now let’s make it hot
:
const sample = Observable.interval(1000).map(x => x + 1).take(10).share();
Thats it, now it’s hot
. The same execution is shared with all down stream subscribers.
If you would like to know what share
actually does, please refer to the Advanced Operators section later in this document.