-
Notifications
You must be signed in to change notification settings - Fork 2
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 last-value/immediate option #29
Comments
That is effectively the kind of feature available in RXJS, whereas this library is more of a replacement for the standard I do see the value in adding such feature though, so I will consider it.
In RXJS such a functional distinction is made at construction time, and so I might follow the same pattern here, by extending IEventOptions. Need to think about that. What do you think? |
Performance-wise the use of an event option at construction time might be best. Thus, you only need to keep a value around, when it's actually intended. However a subscriber (I like that term better than Observer, like with RXJS), will never know then, because it will not be able to willfully set or even retrieve, this option for itself, when it actually subscribes. So from a usage standpoint, it will be best, if the subscriber can determine at subscription time. I would not go so far as to actually provide the old value for reference, or even a flag whether this is a "retained" value. This would be unhelpful most of the time I guess. For me, the first, your, idea would be most straightforward, since I control both the emitter and subscriber, thus will be able to handle the situation optimally for each event type anyway. |
Ok, so I'm thinking now of adding However, it is not clear then what should we do inside once in this case, which takes the same options. Should we treat the last value as the only value or wait for one after, before auto-unsubscribing? 😸 @suterma Any idea? UPDATE(s) The more I think about it, the more I believe that if you pass More problems - method toPromise would need to be extended, for consistency, to also support Not such a simple feature after all 😄 |
Yeah, to keep things simple, one needs to put a lot of thinking into it :-)
Good luck. I have solved my problem at hand, just so you know, for the time being, using my workaround from the initial post. It's doing fine and maybe, just maybe, is the most simple and straightforward way after all. :-) |
This library hasn't been updated in ages. I will need to update everything before adding any new feature. Started with this PR. |
That PR has been merged, a new version 1.9.1 released with tons of updates and changes, except no code changes, hence the minor version increment. This way we now have a good base to start looking at new features ;) |
I have started adding this feature in this PR. |
This feature seems to create a lot of logical problems - race conditions between emitting events, subscribing, notifying and providing the start value. I've been trying to figure it all out, and at the moment I do not see how this will work correctly... I cannot just send the last value when calling I am now thinking of maybe simplifying it, by not having any new option, and instead have UPDATE After a bit more thinking, the latter is also not without problems. If I set this property after the event has been emitted to all subscribers, then new subscribers may miss it even though the |
About immediate unsubscription: Could you not return an already cancelled subscription in this case? This is how I return promises, when there is nothing actually to wait for. E.g. here in my app: https://github.com/suterma/replayer-pwa/blob/de02fc5878831b28b28936dd9ced25ef6a9eb936/src/code/media/AudioFader.ts#L370C1-L372C17 If you have a "lastEvent" property, this might be fine, but would not solve my problem, I still would need to have the additional line of code. Querying the event, instead of the emitter object, but effectively no savings for me. In any case, don't feel obliged to implement this for me personally. It's no deal-breaker for me. |
It is not that simple, subscriptions have events they provide, like when you unsubscribe, which isn't possible to do before a subscription is even created. As per the above UPDATE, adding In other words, I am stuck with this feature for the moment, it does not fit into the existing concurrency model, it creates logical/concurrency problems. P.S. Looking on the bright side, at least I have made a major update of the library with the previous PR, for v1.9.1 |
Kind of, but you would be able to get the last event before creating a new subscription, and not change the code inside the subscription 😉 That way, I think, it is still quite useful, if you think about it, no need re-emitting anything. |
I have just published |
Released v1.10.0, with |
I am currently trying this out. I see however, that some links in the docs are broken, while I was trying to find the documentation of this new feature: e.g. https://vitaly-t.github.io/sub-events/classes/subevent.html#subscribe |
Yeah, the updated automatic web documentation started generating different url-s. I have updated all the links now ;) |
Found it: https://vitaly-t.github.io/sub-events/classes/SubEvent.html#lastEvent Thanks for your effort, it's much appreciated! |
Good! I am closing the issue now, because I am not planning any work in this direction presently. The alternative with subscription promised too many concurrency issues, so we end up with just |
I'll write a "subscribe and initialize with last" function for myself, that I will share with you. This way, I hope, I can get rid of my surplus lines. You might want to include that in your "Extras" or mention somewhere in the docs, or none at all. |
Here is my new "subscript and initialize" method:
It's quite simple and does what I need in one line to call:
It does not have the options (as I don't need these) and it's not yet a protype-added function, but you get the idea. Feel free to incorporate this as an additional way to subscribe. |
If you want to control this on the variable level, you can create your own class for that: import {SubEvent, Subscription, SubFunction, ISubOptions} from 'sub-events';
class SubEventInit<T> extends SubEvent<T> {
subscribe(cb: SubFunction<T>, options?: ISubOptions): Subscription {
const sub = super.subscribe(cb, options);
if (this.lastEvent !== undefined) {
cb(this.lastEvent);
}
return sub;
}
} Otherwise, the full syntax for the custom function subscribeInit<T>(e: SubEvent<T>, cb: SubFunction<T>, options?: ISubOptions) {
const sub = e.subscribe(cb, options);
if (e.lastEvent !== undefined) {
cb(e.lastEvent);
}
return sub;
} |
Thanks @vitaly-t . I am mostly struggling with typings for the prototype addon now. In c# this was simple. Here, I might go with your proposed derived class. Seems to be the next most straightforward way then. And since all my subscribers will be either have initializations or not, it also matches my scenario. Strange thing is though, that I can define the usage of the new class in my interface type, then initialize the property in my concrete class using the basic SubEvent type. It's difficult.... Thanks for sharing! |
I wouldn't spend more time on this. If you need advanced event processing, there is also RXJS 😉 |
I like doing things right, and I love TypeScript. It's my spare-time project so I am always thankful when I can learn something. That said, after all, I am going with a simple local function, like the one you posted last, as all my handler code is in the same class anyway. |
Oh, I have one problem still found, and sorry to bother you. For events that do not have a value, the already emitted events seem not get retained, and lastEvent is seemingly "undefined" event if a previous event actually has been emitted. I explicitly check for undefined, like in your last shared code. Now it can be argued whether events without value should have the above behaviour in the first place, but I have expected to get the callback called. You could, for example, return null (as opposed to undefined) as the last value in these cases. If you decide to leave it as is, I suggest to document this "exceptional" behaviour. |
Technically, it is documented, within Perhaps you can emit |
This specific event of mine is a "ready" event. It is only emitted once ever, the first time a resource is ready for interaction. So, if the subscriber subscribes at a later time, it will never get the ready event. I wanted NOT to be it a boolean, because it will never ever fall back to false, and this definition would suggest otherwise. However, the variant with null worked perfectly for my purpose. Thanks for the hint! |
Hi and first of all thank you for this great event handling framework.
One issue I came across, was that it does not support the receipt of the "last emitted value" at subscription time, like e.g. the "immediate" feature VueJs-Watchers do have.
Context: I have a handler for stuff, that emits various events, some of the events regularly, some seldom. New users (clients) of such handlers register to the various events, but do not get the "current" state of the respective property automatically.
So, right after subscription, the clients need to get the current state, for each event, via an explicit call. This adds quite some boilerplate code, eg. below, for each event/property:
The preferred solution for this would be an additional option to the subscription that initially calls the "updateDuration" function with the last ever emitted value (making the last line in the above example obsolete).
The text was updated successfully, but these errors were encountered: