-
-
Notifications
You must be signed in to change notification settings - Fork 139
Description
I believe this is the most surprising and inconsistent behavior in xstream. The second bullet in the introduction to xstream says "Only "hot" streams", but subscribing to a closed MemoryStream can cause a deep replay of past events. That seems like distinctly "cold" behavior, and it has consequences. It means that the behavior of your program can completely change based on internal state that's outside of the abstraction of Stream.
Scanning through the issues list, I see this over and over. Here's a quick list of issues either fully or partly caused by this:
- Desynchronization downstream of combine #309 is directly caused by this behavior.
- Diamond flow #283 and inconsistency between .of and .fromPromise #282 are related to this and point out inconsistent behavior depending on whether a stream is closed or not
- Number of operator changes behavior of it's input stream. #271 may be related to this ("need to change the way of terminating and resetting a stream")
- MemoryStream doesn't immediately return the cached value to a new subscriber #240 points out a problem with this
- Out of order events with imitate #239 says a workaround is to
compose(delay(0))which sounds awfully familiar and points at the same underlying issue - I just now encountered yet another problem caused fundamentally by this behavior: I have a state machine (or think BehaviorSubject) that gets its starting value from
.startWith('')and is remembered. This stream is not constantly listened to -- it's hooked up to a switch with flatten. Every time it's re-subscribed to, it resets the value of the state machine because it replaysstartWith(). This is external code changing what's supposed to be internal state.
The reason I choose xstream over other libraries is exactly that second bullet: only hot streams. That means I can think in only one direction: forward, and I know that later streams and listeners can't cause side-effects that back-propagate throughout my stream graph. But that's exactly what's happening here: the behavior of my streams can change based on what's happening ten modules downstream.
What's the other side of the argument? Why would you want to keep this behavior?
I've seen the discussion at ReactiveX/rxjs#453, but it's filled with talk of ReplaySubjects and re-connectable observables and exactly the sort of thing I thought "only hot streams" meant we don't have to bother with.