Your summary, and the linked question are both correct, I think the terminology may be confusing you. I propose you think of hot and cold observables as active and passive observables (respectively).
That is, an active (hot) observable will be emitting items whether someone has subscribed or not. The canonical example, again, button click events happen whether someone is listening to them or not. This distinction is important because, if, for example, I click a button and then subscribe to button clicks (in that order), I will not see the button click that has already happened.
A passive (cold) observable will wait until a subscriber exists before emitting items. Imagine a button where you cannot click on it until someone is listening to the events—this would ensure that you always see each and every click event.
Are all Rx observables "cold" (or passive) by default? No, Rx.fromEvent(input, 'click')
for example is a hot (or active) observable.
I also read that Rx.fromEvent(input, 'click')
is a cold observable(?)
That is not the case.
Are there Rx operators which turn a cold observable into a hot observable?
The concept of turning a hot (active) observable into a cold (passive) observable is this: you need to record the events that happen while nothing is subscribed and offer those items (in various ways) to subscribers that come along in the future. One way to do this is to use a Subject. For example, you could use a ReplaySubject
to buffer up items emitted and replay them to future subscribers.
The two operators you named (publish
and share
) both use subjects internally to offer that functionality.
How does it work with Rx operator withLatestFrom
? Let cold$
be a cold observable which has been subscribed to. Will something$.withLatestFrom(cold$,...)
be a hot observable?
If something
is a hot observable, then yes. If something
is a cold observable, then no. Going back to the events example, if something
is a stream of button click events:
var clickWith3 = Rx.fromEvent(input, 'click')
.withLatest(Rx.Observable.from([1, 2, 3]);
Or if I do foo$.withLatestFrom(cold$,...), bar$.withLatestFrom(cold$,...)
and subscribe to foo
and bar
, will I always see the same values for both?
Not always. Again, if foo
and bar
are clicks on different buttons for example, then you would see different values. As well, even if they were the same button, if your combination function (the 2nd argument to withLatest
) does not return the same result for the same inputs, then you would not see the same values (because it would be called twice, as explained below).
I thought Rx.fromEvent
creates cold observables but that is not the case, as mentioned in one of the answers. However, I am still baffled by this behaviour: codepen.io/anon/pen/NqQMJR?editors=101. Different subscriptions get different values from the same observable. Wasn't the click
event shared?
I'll point you to this great answer by Enigmativity to a question I had about the same behaviour. That answer will explain it a lot better than I can, but the gist of it is that the source (the click event) is "shared", yes, but your operations on it are not. If you want to share not just the click event but also the operation on it, you will need to do so explicitly.