Skip to content
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

Killing subscriptions from observers (?) #102

Open
raquo opened this issue Sep 30, 2022 · 0 comments
Open

Killing subscriptions from observers (?) #102

raquo opened this issue Sep 30, 2022 · 0 comments
Labels

Comments

@raquo
Copy link
Owner

raquo commented Sep 30, 2022

This is related to observable completion (#23), but not quite the same feature.

Users should be able to kill a subscription from inside an observer, or more specifically, from where they're defining the subscription. See Iurii's original request on Apr 10 2019 06:07.

Syntax sugar aside, the minimum useful concept would be:

type KillSubscriptionFn = () => Unit  // kills the relevant subscription when called
trait Observable[A] {
  ...
  def addObserver(makeObserver: KillSubscriptionFn => Observer[A])(implicit owner: Owner): Subscription = ???
}

Whereas observable completion feature allows observables to indicate that they have stopped emitting (to all of their observers), this gives users control from the opposite direction – giving individual Observers a way to unsubscribe when they no longer wish to receive updates. I'm not sure, but I think we will eventually want both of those control mechanisms.

Technically, observables are already able to decide if and when to unsubscribe from their parents (by removing their internalObserver from the parent observable), so perhaps we could actually implement this feature on the observable side. For example, in Laminar syntax:

fooStream.withSubscriptionKiller --> { (foo, killSubscription) =>
  if (...)
    killSubscription()
}

Where the withSubscriptionKiller operator creates a new stream which provides a unique killSubscription function to each of its observers, such that said function removes just that one observer. Although, I'm not sure if it's feasible to implement it this way – Airstream observables always emit the same values to all observers. Instead of providing different values to different observers, perhaps we could pass the observer itself as a parameter to killSubscription, but that has other problems.

Still not sure how to do it. Perhaps we could emulate desired behaviour using the stream-completion feature:

fooStream.completeByCallback --> { (foo, complete) =>
  if (...)
    complete()
}

Same style, different semantics / implementation – completeByCallback creates a new stream which will mark itself as complete when the callback is called. So, such a stream shouldn't be shared between several observers if individual observers are to be used.

The problem with implementing this using stream-completion feature is its interaction with restarting streams. I don't remember my latest thinking on this, but I it's possible that observables that complete should never emit again – not even after the user tried stopping and re-starting them. IF that's the case, this might not be desirable for this feature, perhaps what's desired is merely to stop the subscription until it's started again (e.g. if re-mounting the component).

@raquo raquo added the design label Sep 30, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant