-
-
Notifications
You must be signed in to change notification settings - Fork 139
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
combine() exposes inner state #105
Comments
Yes I'm aware of this behavior, but before doing these changes to |
The common case for me as well is to just map it into an object, but in this case it was essentially: xs.combine(a$, b$, c$, $d).map(([a, b, c, d]) => /* HTTP call */).flatten() This shouldn't come up in CycleJS but this is in a hybrid context so things are not quite as pure. I could dropRepeats on each input but it was less messy code-wise to stick a dropRepeats before the map. It's definitely a corner case, maybe more worthy of an FYI in the doc rather than a code change. But I thought I'd bring it up just on the chance someone would walk away with the array reference and wind up with some really confusing behavior. There's probably some way to create an immutable proxy for an array that would prevent that too, although it would still trick the dropRepeats filter. |
Is it possible to dropRepeats on resulting request object in your case? |
I'm thinking that we could attempt to make this fix in |
How exactly? By performing deep comparison each time? |
Not by doing deep comparison inside dropRepeats, but deep comparison in the dropRepeats uses triple equality by default, which may mean equality by value (strings, numbers) or equality by reference (objects, arrays). You should avoid comparing by reference unless you actually want it. So because the combine stream is a stream of arrays, we shouldn't use That's why it's better to do this fix using dropRepeats argument, with deep comparison or hashing, assuming that the internal memory of previous emissions in dropRepeats is not mutated: streamOfArrays.compose(dropRepeats(deepEqual)) streamOfArrays.compose(dropRepeats((x, y) => hashOf(x) === hashOf(y))) |
dropRepeats now checks if the incoming stream value is an array, and slices/clones it before keeping it in memory. This is to support using dropRepeats after a combine and in other use cases where the input stream emits arrays. Closes issue #105.
Fixed in v5.3.6 |
I noticed this when adding dropRepeats to the output of a combine; the stream stopped producing anything.
What appears to be happening is that the combine operator is producing an array, mutating it, and sending the same array again, so dropRepeats ends up comparing the array to itself, in its current state, and it always comes up equal.
It can be worked around by putting map(a => a.slice(0)) in between, but it seems to me this [passing the inner state to next()] is a dangerous practice since user code could end up naively mutating the array and causing subtle bugs.
The text was updated successfully, but these errors were encountered: