-
Notifications
You must be signed in to change notification settings - Fork 1
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
Use executor return value as oncancel handler in Promise constructor #11
Comments
How would you propose distinguishing that it's a token? |
@ljharb The general distinction(/casting?) issue is discussed in #3, we can settle on anything there. For the matter of this feature, let's assume that we detect them by checking whether it has a [[Result]] slot (i.e. the internal shape of a |
Funny, I came up with this exact same idea (returning the oncancel handler from the promise constructor body or "executor") when thinking about this myself. Here is a simple userland implementation:
I'm by no means any kind of promises guru and I am sure that this approach has lots of holes. The advantage is that is requires no tokens or special cancel calls or extensions to Simple example:
Now Let me know what I'm missing. I'm not sure, but I think the I think it would be good enough to put this on the I spent some fair amount of time tonight going through your proposal and others and various threads (thanks for the pointers). Frankly, they all confuse me, and I don't think I'm all that easily confused. |
Actually, not that much. The idea of simply using promises instead of tokens has been circulated before. It works quite nice! The reasons to use tokens is however that they a) allow synchronous inspection of the cancellation state b) cannot fail c) allow special semantics if you need it.
Yes, that's where the approach falls a bit short. In general we desire some way to register callbacks (both result and error ones) to not execute their logic when the cancellation is requested. There were multiple approaches presented:
Can you please let me know where I confused you exactly? I'll try to explain everything and fix the proposal. |
Thank you for your prompt and detailed reply, and sorry to make you rehash stuff that is already out there. It seems to me that the mismatch is that we may be trying to introduce synchronous paradigms for cancellation into the decidedly asynchronous world of promises. In the link you reference, which purports to justify why synchronous promise state examination is necessary--something we'd tell any beginner is a no-no--I don't understand why the problem could not be solved with the addition of one additional
Perhaps we need to examine more closely the trade-off between implementation cost in the broad sense--by which I mean the introduction of new machinery, object types, and signatures, both in terms of the coding-level implementation cost and the cost of people learning the new elements--and functionality including the handling of edge cases, if I may call them that. From a political perspective, I think proposals involving such new machinery are likely to be the subject of endless bikeshedding and people talking past each other, and suffer the fate of many other ES proposals which is to fade into oblivion.
I think I understand this, but if the rejection caused by a cancellation has a reason which is an identifiable type, it can be handled by checking the type:
Which although a bit clumsy seems preferable to new types, new states, and/or new methods on I think there is some generic lesson to be learned here from observables. Observables do not involve any separate machinery for cancelling or terminating or throwing. Other observables themselves are used for such things. So one observable can be combined with another one in such a way that something emitting on the first shuts down the second, etc. |
The reason we tell beginners to avoid inspection is because they tend to use it where it is unnecessary and would only complicate things.
That cannot work. It would block the code until the cancellation is requested, and not execute the actual operation at all.
Uh, an identifyable type does need a new type. Especially if there is supposed to be a try-syntax for it. And also I believe that cancellation as a rejection type does not solve the chaining problem at all. It works well if you are the subscriber of a cancellable promise, who just wants to distinguish the outcome. A().then(B).then(C).then(showResult).catch(showError) then the behaviour we want is that
Also we typically want the Promise.race([cancel,
Promise.race([cancel,
Promise.race([cancel,
A()
]).then(B)
]).then(C)
]).then(showResult).catch(showError) This is where Domenic's proposal falls short, and my approach has its foundations:
|
I meant a new first-class type, not one new error type. As for boilerplate, by definition it can always be abstracted away. Just as an example, one can imagine a catch handler factory perhaps called
which would be implemented as
That seems acceptably streamlined and less intrusive than new methods on the So let's move on to the interesting stuff which is cascading of cancellations down the chain.
We assume that
If
The issue here is of course is that In any case, in the realm of syntactic sugar, one could image machinery to ease this requirement in the form of utilities (again, either built-in or written by users), such as
the result of which could be run by
Well, I'm sort of running out of gas here, and none of this addresses the need to cancel a promise RIGHT NOW if that is considered non-negotiable. Still, I continue to believe that this sort of approach could be the right trade-off between complexity and functionality, and between baked-in features and features left up to users to wrap. |
Indeed. If they are cancellable functions, the chain would look like A(token).then(x=>B(x, token)).then(y=>C(y, token)).… But what I am mostly concerned about functions that are not cancellable, or not asynchronous at all. What if I did
If
Exactly that is what my proposal is, a utility for cancellation (tokens) built into |
Also, note that |
Here is something: https://github.com/rtm/cancelable-promises |
In case you're interested, I've completely re-engineered my approach, which now treats canceled promises as being in a permanently pending state: |
Interesting, but I've already made a case for rejection. |
would be an extraordinarily convenient syntax to create cancellable promises.
The returned function would be installed as a cancellation handler on
token
, and removed from it as soon asresolve
orreject
are called.If nothing callable is returned or no token is passed to the constructor it doesn't do anything.
Domenic has brainstormed a
Promise.cancellable
helper, I have used this pattern before in F-Promise and I have also shown it in the examples.token.subscribeOrCall
solves a similar problem.By only doing anything about the return value when a token is passed, this feature would be fully backwards-compatible.
The text was updated successfully, but these errors were encountered: