-
-
Notifications
You must be signed in to change notification settings - Fork 31
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
subscribe should return subscriptionInfo object with an unsubscribe/cancel function #10
Comments
Another thing that might be worth considering is returning a "subscription/cancellation token" (number) rather than a function. Breeze uses this pattern as well as |
It would be if it avoided creating the closure as part of the dispose code. Currently our EA creates a closure and so would the above mechanism, most likely. However, I'm not too concerned about it in this case because you would have to have a ton of messages for it to matter. (That's one reason we need to change the binding system. It creates these closures in the same way...and that's a case where it really does matter.) |
In following the pattern below
I have setup an EA to subscribe and then call the unsubscribe in the detach function of my view-model. However this doesn't seem to work at all. Users.js
Welcome.js
If I go to users, then go to welcome. the console prints: It is also the same if I use |
@digitzfone I think you meant |
Yes, your right I do mean |
Right, the reason is because the navigation lifecycle is going to run like this:
So, because you are publishing the message in the constructor, it will be received by the old screen because the new screen's constructor is executed before the old screen is deactivated. The reason for this is that if the new screen returns false for a potential canActivate call, then we're in a bind if we've already deactivated the old screen, which should not have been deactivated. |
So the issue has been closed and the API remains the same ? Not sure I understand what happened here. |
I follow, It isn't an issue. It was an event order problem. My new constructor was firing a publish message before the old detached was able to dispose of the subscription. I need to reverse the order. So I will move my dispose to the old deactivate and move my publish to the new activate. |
@tlvenn Sorry for the confusion. We aren't planning to change the api at this time. |
And what is the reasoning behind not trying to make the API clearer and more readable ? Pretty much all pubsub system and even Observable follow the same pattern of returning a subscription you can call dispose() or unsubscribe() on. As i outlined above, beside being a pretty bad design choice imho, it's confusing as hell for any people new to Aurelia as it is absolutely counter intuitive and against everything they are used to. |
I'll tell you what...if you sign our cla and submit a PR with unit tests, I will accept the design change. It needs to happen within the next 10 days or so. |
I am absolutely fine with that :) |
Actually I believe I have signed the CLA a long time ago.. |
btw @digitzfone please create your own issue next time ;) |
Is the API changing to return this? {
channel: 'test',
subscribedAt: dateProperty,
unsubscribe: function() {...}
} I don't find any of the above^^^ to be useful. The existing EventAggregator can easily be wrapped to provide this API. If we are going to make a change I propose we match the This pattern applied to the EventAggregator would look like this: // subscribe:
let subscription = ea.subscribe(LocaleChangedEvent, callback);
// unsubscribe:
ea.unsubscribe(subscription); Implementation detail: this design would remove the closure involved with creating the "dispose" function by returning the index into the callbacks array as the "subscription id" That said, I find the current API to be the simplest of all the proposed alternatives. Thoughts? |
Hi Jeremy, I dont think it's really fair or appropriate to try to compare those rather simple JS functions that are completely autonomous with a pub sub system where you create channels, consumers and producers which use those channels to communicate. And as far as I know, most are designed the way I describe more or less. Furthermore I dont think it's desirable that the subscription cannot by itself unsubscribe because it would lead to injecting the ea pretty much everywhere where you could potentially need to do it. |
Ya I agree but the issue is that out of the box it does not and everyone who tries to leverage the EA will ponder how to unsubscribe. And really, am i the only one thinking that having this code:
Is completely unreadable ?? As far as i know, I am calling a constructor while actually it's kinda a destructor so it completely hide the purpose in a very dangerous way. |
Before we commit to a final decision, let's consider:
@tlvenn BTW The sample code you are showing is much more readable when you write it the way I do when I use it:
|
When you know what to expect because you know the API, yes it would be clearer but still having unsubscribe assigned to a call to the subscribe method is little bit weird. And unfortunately you cant really control how people gonna name their variables but you do control the naming of the API methods and so you should try to help them as much as possible to write readable clean code. |
It is a matter of opinion. Obviously I don't find it strange at all ;) It also seems more light-weight than your proposal, though not as light-weight as @jdanyow 's. I'm inclined to think that in all three approaches, the developer would have to read the documentation to understand the pattern anyway. The problem today is that there isn't any real example of disposing of a subscription at all in the docs, which makes it harder to learn in general. I do like the idea of being able to pass around the subscription/disposal object without needing the ea for unsubscribe. So, I think that's a point against @jdanyow 's idea. So, there are trade offs. @tlvenn What could push me over the edge to your approach would be if you could show that it performed better than just returning a function. Or that the memory pressure was significantly reduced. To do that you would need to write some benchmarks. You can see our benchmark app repo for that. Start by submitting some PRs to the benchmark repo to add new benchmarks for the existing event aggregator. After that, create a fork of the current EA and make your changes (in this case along with benchmark forks) and then compare the performance and memory of both versions. If you can show that returning an object is more efficient, then that's a good argument. Otherwise, I'm not sure the advantages are great enough to make a breaking change to the API, particularly one that we've heard no negative feedback on aside from this issue. Also, we are on a tight timeline now as we approach beta, so it would need to be wrapped up in about two weeks. |
FYI, you probably don't want to return an ad hoc object. You probably want to create a class to describe the subscription for perf reasons. |
Hi Rob, I respect your opinion and we could argue that at the end of the day, it's a matter of coding style and to each their own. But and it's a big one, you are writing public APIs and a framework for other people to consume not for yourself. So it needs to gather traction and to do that, one of the appeal is how easy and clean the code would be and how intuitive the API is. And that is one thing you sell well when you compare it to NG2 for example. Overall Aurelia is a pleasure to work with and pretty intuitive. The EA is not, plain and simple. As for your benchmark question, I would first ask what kind of benchmark do you already have that would prove that the impact of one more object times the live subscriptions a given system on average would have, could significantly impact the memory footprint of the EA that you are willing to tradeoff good naming convention over performance. If the EA is such a performance bottleneck, you should already have some benchmark in place to measure any improvement you think you are making. Then it should be trivial to branch it and test a new approach. Unless proven otherwise, I would favour good naming convention that improve code readability. |
The api right now around how to un subscribe is not really obvious and I see many people in Gitter asking how to do it which lead to something like this:
Which is really weird when you look back at the code and does not reflect at all what is really going on.
Ideally, the Event Aggregator should return a subscription object such as:
So people can do:
What do you think ?
The text was updated successfully, but these errors were encountered: