-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Why doesn't a hot observable stay hot? #1148
Comments
Well, the hot observable did stay hot, it's just that there's a cold observable returned by If you don't want the projection function from |
Why would you ever want the projection function from |
@jhoguet because, 1. Observables are decoupled, such that Observables are a language-agnostic push-implementation of Haskell's (potentially infinite) lists. An Observable is a monad, aka a computation that you can compose with map, concat, reduce, and flatMap. You compose the Observable computation once, but you can execute the computation any number of times. Most operator Observables (including
The question, "why don't hot Observables multicast every operator?" is fair, but the answer is mundane: it's a classic space-time trade-off. Multicasting every operator requires allocating memory to track multiple Subscribers for each operator. Most operators won't have multiple subscribers, but there's no way to guarantee that, and thus no safe optimization we can make for that. Resubscribing to the source is the cheaper option (and only grows with your subscription). |
Simple. Consider Then cold = clicks.map(() => Math.random());
cold.subscribe(console.log); // 3, 70, 28, 58, ...
cold.subscribe(console.log); // 62, 81, 4, 9, ... There are applications for that. Say you want to make a game, and each subscription is a toss of the die. Multiple subscriptions mean you have many dice. The dice are tossed at each click. Usually the mapping is a pure function, though, so it always gives the same output: cold = hotNumbers.map(x => 2 * i);
hot.subscribe(console.log); // 1, 2, 3, 4, ...
cold.subscribe(console.log); // 2, 4, 6, 8, ...
cold.subscribe(console.log); // 2, 4, 6, 8, ...
// cold looks hot because same events happen at the same time The point of cold-by-default is: one-observer-per-observable is cheaper (this confirms what Paul just said above about the tradeoff). So many-observers-per-observables is an opt-in. You usually don't need hot, but when you need it, you are in control, you choose to be hot. |
Thank you @staltz @Blesh and @trxcllnt In summary, operators create new observables instead of sharing the subscription to the hot observable for performance reasons. This is desired because a hot observable being subscribed to more than once is rare. My limited experience has not been consistent with this. I have a lot of code that is having to call Thanks again for considering this request. |
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Why doesn't a hot observable stay hot?
For instance...
outputs
But this is not what I would expect. I can fix this by using
o.share()
But why would I need to do that? Given that the Subject is pushing the same input, I should get the same output to functions like map. Isn't this the whole point of shifting to an RFP approach? From my point of view this only benefits those that are causing side effects in map because otherwise they would never know or care. Given that you have an operator like do we could preserve the current default by making do be the point at which the observable stops sharing.
I suspect there is either a fundamental RFP reason for this which I have not learned yet, or this is incidental complexity caused by some implementation detail. If it is the latter I would love to find a way to fix that before 5 comes out of beta.
Moved the question from #1121 (comment)
@trxcllnt provided some great feedback that the
.map
is producing a new cold observable hereThis is not what I would expect. I would not expect two subscribers to get different values from the same
map
of the sameSubject
. Therefore the computation of themap
should be memoized / only happen once for all subscribers.Because this isn't true, I need to re-coerce the Observable back to hot everytime I perform an operation on it by calling
share
on it.While this doesn't seem terrible in one module
it starts to smell like a leaking concern when the operations are happening across modules.
It adds to the cognitive overhead of using RxJS as I need to track which observables are hot or cold or sacrifice performance by recomputing unnecessarily.
Why doesn't a hot observable stay hot?
PS - I have been watching the hard work you guys are doing and am very thankful!
The text was updated successfully, but these errors were encountered: