I understand the differences between hot and cold observables, but I always see people using hot observables instead of cold; in fact, if someone accidentally uses a cold observable it's considered a mistake as it's often a cause of unwanted behaviors.
What's a case where you would prefer or use a cold observable over a hot one?
An Observable is cold when data is produced inside the Observable and the Observable is hot when the data is produced outside the Observable.
A cold observable starts producing data when some code invokes a subscribe() function on it. For example, your app may declare an observable providing a URL on the server to get certain products. The request will be made only when you subscribe to it.
A typical example of a hot observable are mousemove events. The mouse moves happen regardless if someone is listening or not. When we start listening for them, we only get future events. Cold Observables on the other hand are the lazy ones.
There are two main ways for converting a hot observable into a cold one: defer to defer its existence entirely or replay + autoConnect(0) to pre-run it and just replay to others as a cold one.
First of all, I invite you to review Hot and Cold observables : are there 'hot' and 'cold' operators? to make sure you have a thorough understanding of hot vs. cold.
Cold observables allow for lazyness of producers, and this is a very desirable feature. It is a waste to produce values (production could be expensive) when there is no use made of those values (no consumers). As such cold observables are the building block... from which more often hot observables are derived.
As such the most common use case for cold observables is to lazily derive hot observables. If you think about it, you need to programatically construct these hot observables somehow. One way is to use subjects (you then are the producer). The other way is to derive them from other preexisting observables through operators, preexisting observables which are also derived from others etc.. At the end of the chain, you should find Rx.Observable.create
and that is a cold observable.
You use cold observable when you need lazyness (starting producing values only when there are consumers, or controlling the start of the producing process). For example, defer
allows you to start a producer only when there is a consumer. It can be used when you have for example a hot observable but you are not ready yet to listen to it.
You also need cold observables when you need to reproduce a value-producing process (every new subscriber will restart the same exact process). This is for example the case for testing purposes, where you want to use the exact same sequence several times but with different consumers and at different times.
In the end, the question sounds more like a philosophical one. You have two tools at your disposal, what matters is understand what you need, what you have, and which works for your use case.
The core of the answer lies in Ben Lesh's laconic summary:
TL;DR: You want a HOT observable when you don’t want to create your producer over and over again.
In direct answer to the question "What's a case where you would prefer or use a cold observable over a hot one?", I'll offer both a general answer and a specific example.
Generally, it is far more convenient to use a cold observable to model streams that are created each time they are required than to create a hot one and try to wrangle it.
Specifically, consider the following trivial example. Say you want to respond to a click on a button by counting down from 10. If the button is clicked again during the countdown, it starts again at 10. If click$ models the button events, you might have something like this:
const subscription = click$
.flatMapLatest(_ => Rx.Observable.interval(1000).take(10))
.select(x => 10 - x)
.subscribe(x => console.log('clicked: ' + x));
Consider how this would be modelled without a cold observable. How would you:
1 and 3 can be addressed pretty easily, but 2 and 4 are nasty.
In answer to your second question "Is it laziness?" I would argue that it is not. A cold observable can leave it until the moment of subscription to produce its values. A hot observable can leave it until the moment of subscription to hook the appropriate events. They are both lazy in their own way (or at least, can be). The key difference lies in what Ben Lesh said: do you want to create a producer each time? And sometimes, you really do.
What's a case where you would prefer or use a cold observable over a hot one?
I hope I'm not stating the obvious, but any situation where you want to access all values (or some subset arrived at by filtering the complete set) from an observable's history.
The first example that comes to mind is averaging all of a student's test scores, not just the scores that have arrived after you've subscribed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With