-
-
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
Add spacedWith combinator #50
Comments
These look like they would be very nice to have if one had a need for such timing logic. What are some canonical use cases? Do you know if other streaming libraries have similar operators? Some implementation notes and decisions to make:
btw another timing operator that's sorely missing is |
I had a use case for something similar, though a bit different and simpler: It behaves like My naive implementation is: def mapDelay(projectMs: A => Double): EventStream[A] = {
new MapDelayEventStream(parent = underlying, projectMs)
} class MapDelayEventStream[A](
override protected val parent: EventStream[A],
projectDelayMillis: A => Double
) extends EventStream[A]
with SingleParentObservable[A, A]
with InternalNextErrorObserver[A] {
/**
* Async stream, so reset rank
*/
override protected[airstream] val topoRank: Int = 1
override protected[airstream] def onNext(nextValue: A, transaction: Transaction): Unit = {
val _ = js.timers.setTimeout(projectDelayMillis(nextValue)) {
val _ = new Transaction(fireValue(nextValue, _))
}
}
override def onError(nextError: Throwable, transaction: Transaction): Unit = {
val _ = new Transaction(fireError(nextError, _))
}
} |
My use case was related to having auth tokens with expiration. I had a stream of tokens, and used this combinator to kick off the token refresh logic. |
Yeah I was thinking of expanding the `delay` operator to match the
customization of `periodic` or `spaced`.
Now I'm also wondering if the dynamic delay / spacing Millis value should
be based on the previous emitted value, or the current value...
…On Fri., Dec. 25, 2020, 9:55 p.m. Iurii Malchenko, ***@***.***> wrote:
My use case was related to having auth tokens with expiration. I had a
stream of tokens, and used this combinator to kick off the token refresh
logic.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#50 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAECBMABIACFIPMHQWINFRDSWV3EFANCNFSM4VJBVYMQ>
.
|
I am building a multiplayer card game (similar to Poker) where game updates are published to a client in a (websocket) stream.
If it simplifies the implementation,
I haven't had a use for this but should be doable.
What would happen if the pending timeouts are not cancelled?
Note that
If pending events are not cancelled, then the first event post restart must be spaced.
Yes, this is all that is required for spacing. |
I think spaced makes much less sense on Signals. |
It's actually the opposite, unless there is good reason to want a new transaction or an async boundary, we shouldn't introduce these. It will behave better wrt glitches. Regarding behaviour on start and stop:
That was actually what prompted by query. I just fixed that yesterday in eaca9ca (and Debounce too, in another commit). Generally, Airstream's contract is that stopping an observable clears its state and stops emitting further events. Signals can't clear their current value, but everything else that the observable accumulated is generally cleared. Imagine you have a component (Laminar element) that uses a spaced stream to lay out your cards. You unmount it while the cards are being laid out. Once it's unmounted, the stream has no more listeners, so even if it fires, nobody will be there to hear it, and nothing will happen, the event will be lost. That's expected, and there is no way around it. You shouldn't stop the stream if you want it running. But, now imagine that you quickly re-mount the same component. The stream becomes active again. If you did NOT clear the queue of pending events when it stopped, some or all of those events might still fire after the component is re-mounted. But whether they will be observed, depends on timing. So this becomes really unpredictable and also unexpected. For example, re-mounting that component could trigger a new request to the backend, and you'd expect to start receiving new spaced card layout events from the result of that request, but you will instead start receiving card layout events that were pending from the previous request from before the component was unmounted. Or not, depends on timing. That's why it's important to have the observable clear its state when it's stopped. Hope that makes sense. Perhaps we could at some point add an operator like |
Hard for me to say, but if we don't make it available on signals, people will still be able to use it via So I think this operator should be defined on signals too, and it shouldn't be too hard to do that. |
Behavior:
I can submit a PR if this looks useful.
The text was updated successfully, but these errors were encountered: