Replies: 1 comment 1 reply
-
The convention in RxJS is that observables are "unicast" per subscriber by default. This means that every new subscriber will have some sort of internal state for that observable. For example: const observable$ = interval(1000);
observable$.subscribe(v => console.log(v)); // Will log 0... 1... 2... 3...
setTimeout(() => {
observable$.subscribe(v => console.log(v)); // Will still log 0... 1... 2... 3... independently
}, 5000); In some cases you actually need this behaviour, and for the others, you can create a multicast observable by using one of the share operators. What I usually do is only share those observables that can be referenced from more than another observable. If it's a small observable that I'm declaring in a file without exporting it, where it's just to break down a bigger problem into small chunks, I usually don't do any In your case it looks like the only observable that needs to be multicast is
As for [2] I would say don't be afraid of creating your own operators. I tried thinking about this specific problem for a little time and I couldn't think of any good default operator that could do this, so I would either use |
Beta Was this translation helpful? Give feedback.
-
My Problem
I want to learn more about writing declarative/functional code with RxJS. I'm trying to use splitting, merging, and other forms of stream coordination to encapsulate the logic, rather than imperatively handling things. I have an example scenario that hopefully you can help me with.
Context
When a user clicks, I want to log statistics about their click & hover behavior. I also want to show a notification if the statistics are considered 'primary'.
Here is how the above streams currently work. Each color represents the code that is run due to each subscription. All of the upstream work is repeated for each subscriber (buffering the events, and calculating the stats for primary).
But here is how I actually want it to work. Where the work that is done along the pipeline is not repeated, and each subscriber only handles its part.
To fix this, I added few
share()
operators, in order to multicast the work that has already been done.The type of flow I am trying to replicate looks like this with plain functions.
or like this with a
map
in the original codeQuestions
Is adding
share
to your streams really necessary to allow RxJS to work this way? In the 'plain functions' example above, it seems very simple and nothing out of the ordinary, but when you try to do it by splitting up the streams into separate events, duplicate upstream work is done which seems a bit unintuitive to me.I feel like I'm missing something. Is this not a good way to go about writing RxJS? I feels so right, when thinking about the logic in terms of the diagrams above, like interconnected streams... but the overhead of
share
seems weird. Should I just stick to something like themap
solution in the last code example?(unrelated question) I used
buffer
to get the latest hover event on click. I was thinking about usingReplaySubject
andwithLatestFrom()
, to reduce the in-memory storage of hover events (because I only need the latest one).but this doesn't work because I need the
click$
event to clear whatever hover events have already passed. For example, if a user clicks 2 times in a row without hovering on anything, I don't want a stale/old hover event to be retrieved.Is there a better way to do this without
buffer
? It seems wasteful to store all the events in memory just to get the last one. I was hoping to find a size configuration onbuffer
, and set it to 1, but I don't see any.Beta Was this translation helpful? Give feedback.
All reactions