Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the use case for cold observables?

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?

like image 706
m0meni Avatar asked May 01 '16 15:05

m0meni


People also ask

What is the difference between Hot & Cold observable?

An Observable is cold when data is produced inside the Observable and the Observable is hot when the data is produced outside the Observable.

How do you make a cold 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.

Which of the following is an example of a hot observable?

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.

Which is the better choice if we are to convert from a hot to a cold observable?

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.


3 Answers

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.

like image 190
user3743222 Avatar answered Oct 21 '22 04:10

user3743222


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. Initialize a stream in advance so that appropriate values were available when required?
  2. Avoid having to deal with the fraction of a second between the interval ticks and the time of your subscription?
  3. Deal with ordinals that can start at any number rather than just 1?
  4. Manage clean up logic for the stream?

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.

like image 4
Matt Burnell Avatar answered Oct 21 '22 02:10

Matt Burnell


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.

like image 2
pdoherty926 Avatar answered Oct 21 '22 03:10

pdoherty926