-
-
Notifications
You must be signed in to change notification settings - Fork 28
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
Investigate Observable Completion #23
Comments
Somewhat relevant suggestion from @yurique: https://gitter.im/Laminar_/Lobby?at=5cadea9d8148e555b27f5ce5 |
More thoughts on observable completion:
|
This is not going to make it into 0.15.0. I'm still struggling to find a good solution for the problem. The problem is not as much technical, but mostly conceptual – if the observable is allowed to emit after it was completed then is stopped and started again, then completion does not mean much, and does not allow for any optimizations – all we'd get from that is a concat method. On the other hand, if observables can only complete once, that would allow some optimizations, but would be of very limited use, as you wouldn't be able to restart such an observable when remounting the component. Maybe that would be ok, but I find it hard to judge that due to apparent lack of real world use cases requiring this feature. It seems that most people don't care about this feature, and of those who mentioned who mentioned wanting this, most solved the problem by using |
Currently Airstream has no concept of "completing" observables.
Completion is a special message emitted by an observable that notifies all observers – both internal and external – that the observable is done and will not produce any more events. Imagine
onComplete()
in addition toonNext(event)
andonError(err)
.This concept is a natural fit for event streams, but it needs to be adapted to signals. Unlike streams, Signals carry a current value, so for Signals completion also means that their current value will no longer change.
For example,
Val
-s would be completed on initialization.stream.take(1)
would complete after one event. If Airstream had atake
operator, that is. It doesn't, and I think we must at least have that much before we go all the way to implement completion.The benefits of completion as a feature are not quite clear to me at the moment. I'm yet to see a real life pattern that requires completion. Which is not to say that such patterns don't exist, I just haven't run into them myself yet, or maybe I just tend to structure my code differently because I have Signals in Airstream. Not quite sure.
As for performance...
Completion will allow all child observables to remove themselves as internal observers from the completed observable. The completed observable can actually do this by itself without the completion feature, but what the completion feature allows is propagating this completion down the chain of observables – since an observable that only depends on completed observables is (generally) considered completed.
This chain reaction can result in early disposal of completed observables and subscriptions, which could potentially reduce memory usage (a subscription that looks at a completed observable can be killed without waiting for the owner to kill it).
One practical application where this could be useful is a pattern where an a parent component renders a dynamic list of children, and has an event bus that is sourced from streams generated by those children. With completion feature, we would complete the streams exposed by a child component when said child gets unmounted, the parent's event bus would be notified about that and would stop listening to this completed stream.
However, we already have a solution for this:
eventBus.writer.addSource
requires an Owner which will remove the source observable from event bus (e.g. when the component it belongs to is unmounted). Granted, this is a rather ad-hoc solution whereas completion would be a generalized solution to this problem.But I'm not sure how useful completion is outside of this pattern. All the cases I ran into where I wished for completion for a performance gain involved firing one event before completing. That does not feel like much of an Observable to me, and I'm not sure if Observables should be optimized for what essentially is a singular callback pattern.
Is
component.$mountEvents.collect { case ev: NodeDidMount => ev }.foreach(doStuff)
all that better than a simplecomponent.onMount(doStuff)
callback? Is it such a big a problem that this stream does not stop after aNodeDidMount
event was published (let's assume there will only ever be one such event)? Should this be solved differently, perhaps with a.once(doStuff)
, a new method that will unsubscibe the observer after one event?Ultimately, observable completion is a big feature, and has complex interactions with other features. Without a clear need, it will remain unimplemented for now. I just wanted to get this out of my head.
The text was updated successfully, but these errors were encountered: