Replies: 1 comment 4 replies
-
I'm sorry. This design is a hard "no" from me. For some of the same reasons I explained in the other thread here: #7243 (reply in thread) I can see that you're trying to address those concerns, but I think the proposed API here is still clunky. There's an additional problem with BOTH of our proposed solutions in that it means the RxJS operators are proprietary again, when I went to some lengths to try to make them observable agnostic in newer versions of 8.x. I can tell that you're passionate about this solution, and you've put a lot of thought and time into it, and I'm so very sorry, but I'm actually going to close both this issue and the other for now. As I have a different proposal coming. |
Beta Was this translation helpful? Give feedback.
-
This proposal is triggered from the discussion in the RFC #7243, which suggests adding
owner: Subscription | Subscriber
as an optional parameter to theObservable.subscribe
method.The main goal of this one is to solve the same problem as the original RFC, but at the same time standardizing how Observers expose their lifetime (Partial observers, Subscribers and Subjects).
Authors
This proposal is co-authored by @voliva and @josepot
Problem space
The current API of
subscribe
has two overloads: shorthand and partial observer:This has the problem that
source.subscribe
doesn't know the lifetime of the observer, in other words, the observer can't stop the subscription.Once
.subscribe
returns the Subscription, then the consumer can call.unsubscribe(
to stop it, but this might not be an option ifsource
emits a large amount of values synchronously, which is what's called a "firehose" in the original RFC.With the current API there's another place we deal with Observers: We get a
Subscriber
when creating a new observable:The Subscriber is both a Subscription and an Observer, in other words, it's an Observer that also has the information about its lifetime: It can notify the source when it should be disposed.
The problem is that Subscriber is an implementation detail, and
new Observable
leaks it. It's used internally to solve the firehose issue when creating operators, but it's something that consumers shouldn't really use.On the other hand this also adds in confusion on what's the difference between an Observer and a Subscriber.
And lastly we also have another kind of Observer, which is a
Subject
.A Subject is an Observable and an Observer, but also has a lifetime by its own. It's not fully a Subscription, but it does have an
.unsubscribe()
method that closes it.In the past, a Subject had a property
isStopped
(or going further into the past,isUnsubscribed
), but this was marked as internal and then removed for v8.0. This is just another observer lifecycle which has a different way of getting represented than the other cases.The original RFC proposes to add an
owner
configuration option on theObservable.subscribe
function that would allow the consumer to manage the lifetime of the subscription for synchronous values.And this helps consumers build operators that would work with a firehose source. However, this looks like a perfect opportunity to let Observers have a consistent way of exposing what is their lifetime, in a way that it solves the same problem that the original RFC fixes.
Proposal: add a property to Observers that exposes their lifetime
The
Observer
interface changes the interface with a new property with its lifetime:Observable.subscribe keeps the existing signature
And all interfaces that extend
Observer
will also have theowner
subscription - Subscribers and Subjects.In fact, Subscribers can be removed, which has the advantage that the API won't have to leak an internal implementational detail.
To ease migration, the original
unsubscribe
function could be added to theobserver
returned by the Observable constructor, which would just callthis.owner.unsubscribe()
.Lastly
Subjects
would also have theirowner
exposed, which is just a reference to their Subscription. This will make it consistent with the rest of the Observers, and it will let subjects with complex lifetimes to expose that in a consistent way.The following example shows a
share()
implemented with this proposal, compared to the original RFC's API.Another advantage that moving lifetime management to
owner
on the subject, is thattap
would work with a Subject again (it's currently broken because tap calls 'unsubscribe' #7078), because that action would now be moved tosubject.owner.unsubscribe()
. This is just another example of how having a consistent API often leads into good interop.We are not completely familiar with the current internals of RxJS, but we really think this would be a very good addition, and would make the API consistent, simpler and less bug-prone to use.
We also agree this might be a big change, so it's possible that it might not be possible to implement it for the next major release (8.0), but we still think it could be used as part of a bigger roadmap across multiple releases.
cc @benlesh
Beta Was this translation helpful? Give feedback.
All reactions