Comments (2)
I don't remember having problems related to this, either.
But I'm usually only using .fromValue(..)
to "pre-start" some other stream of events (like in EventStream.merge( fromValue( ... ), buttonClicksStream )
).
from airstream.
I think I fixed this. The fix is pretty simple, but I had to arrive at it the hard way, after trying out increasingly complicated mechanisms that did not work.
The suffering
Initially I was operating under an assumption that I want or need to fire events that are emitted onStart by all of the streams listed in the Scope section in a shared transaction, similarly to how we handle events emitted onStart by signal.changes
. This turned out to be both undesirable and seemingly impossible to get right.
It's hard to get right due to weird cases like EventStrean.fromSeq
that emit multiple events onStart. The second and subsequent events can not be emitted in the shared transaction, because an observable can only emit once in any given transaction. However, I wasn't able to figure out how to schedule the execution of those subsequent transactions in a universally desirable and predictable order. Interactions with other features like flattening, and SyncObservable-s make me think that this is in fact not possible to do safely in the general sense, and that fromSeq could be only a private case of a bigger, problem that is unsolvable in principle, for the same reasons that we need transactions in the first place.
But this is all moot, because the behaviour I was trying to achieve is actually undesirable. I realized that signal.changes
is different from all other streams in a rather fundamental way – its output does not create events from thin air, it gets them from a parent observable, and does not normally create its own transactions. All other streams in the Scope list are the opposite – they create their own events [1], and always fire them in new transactions. Because of that, there is no reason to shove all those events (that are normally fired in separate transactions) into one shared transaction – all we need to do is to delay the execution of those transactions until the Transaction.onStart.shared
callback is finished, i.e. (in practical terms as it relates to this ticket's stated problem) until all subscribers have been added.
[1] Except the flatten
ones, I will have to think about those again.
The actual solution
So, that's what I did. Now, any transaction created inside Transaction.onStart.shared
is added to a separate postStartTransactions
queue. After everything else is done, but before the shared
block relinquishes control, each of those transactions is scheduled for execution after the current (shared) transaction, in the same order.
I also fixed a bug where multiple signal.changes
would fire in the wrong order in the shared onStart transaction under certain conditions, and a bug where signal.changes
wouldn't fire at all on start (not sure if that one was possible to encounter with typical Laminar usage, but it was possible in manual Airstream usage).
Try it out
I published Airstream 17.0.0-M1
with this fix. It should be binary compatible with Laminar & Airstream 16.0.0. If you are using Laminar 16.0.0, please add "com.raquo" %%% "airstream" % "17.0.0-M1"
to your dependencies, and see if anything breaks (primary scope: elements with streams mentioned in Scope getting mounted). Everything should work fine, unless you're implicitly relying on this bug, which is unlikely.
That said, there could be slight differences in the order of events fired when mounting elements. For example, now signal.changes
will emit before all other transactions such as EventStream.fromSeq
, whereas previously it would depend on their relative order. (Remember, this is only when starting / re-starting multiple observables at the same time, e.g. when mounting an element that contains several subscriptions).
If you try it out, please subscribe to this issue to get notified of any problems reported by other users.
from airstream.
Related Issues (20)
- .split operator is hard to use without Laminar
- Killing subscriptions from observers (?)
- splitByType / splitByEnum HOT 6
- Can `DerivedVar` support `map/update` semantics in addition to `map/contramap` semantics? HOT 2
- Add an AjaxStream upload progress observer
- FetchStream does not emit events if it's initialized outside of a transaction HOT 1
- [Question] Simulate DomEventStream click on page load HOT 5
- idiomatic usage of foreach for EventStream HOT 4
- RFC: Should we import-gate flatMap? HOT 7
- Vars should be splittable HOT 4
- Error: code length overflow HOT 2
- Transaction stack overflow caused by sibling transactions HOT 4
- split doesn't memoize on Signal[LazyList[A]] HOT 2
- Zooming into a Var should not require an Owner? HOT 5
- SplitChildSignal does not re-sync when restarted HOT 6
- `composeEither`: fixed-scope `flatten` without transcations HOT 4
- Add method variant of EvenStream.merge? HOT 5
- Update and get HOT 5
- add flatmap to ReactiveEventProp HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from airstream.