-
Notifications
You must be signed in to change notification settings - Fork 94
Closed
Labels
Description
The only use case I can think of the current API doesn't address is handing out the capability to resolve/reject a promise. We can of course do:
var resolve, reject, promise;
promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
...but it's a bit awkward. Should we add Promise.deferred
exposing GetDeferred
?
Metadata
Metadata
Assignees
Labels
Projects
Milestone
Relationships
Development
Select code repository
Activity
domenic commentedon Dec 2, 2013
The reasoning behind not adding deferreds is that they are usually are an anti-pattern and, even worse, an extra concept to learn. They’ve proven troublesome in user-space, and the promise constructor has proven to be a great fix. The only reason the spec uses it so much is because creating closures in ECMASpeak is a pain, so we encapsulate that in a single operation. This in turn causes us to have to manually re-capture exceptions and forward them to
deferred.reject
(see e.g. all the RejectIfAbrupts inPromise.all
andPromise.race
). Bad news bears.petkaantonov commentedon Dec 2, 2013
I should really change the rantish and hostile tone in that article :D
juandopazo commentedon Dec 2, 2013
I totally share the sentiment of that article, but the bad practice still happens with the promise constructor. It just looks like this:
stefanpenner commentedon Dec 2, 2013
@juandopazo or
or with something like
Promise.method
Additionally, the Promise constructor approach catches exceptions and propagates them as one would expect.
domenic commentedon Dec 2, 2013
This is one of the stronger arguments against deferreds, in practice.
juandopazo commentedon Dec 2, 2013
That´s a good point.
I guess sharing
resolve
is an obscure enough practice so adding a shorthand could do more harm than good.stefanpenner commentedon Dec 2, 2013
@domenic ya.
Additionally, it appears that modeling the promise as the thing that is the potential future value results in much more understandable and maintainable code. Using a deferred seems to almost always spiral away from this. Nearly each time I see a deferred used, it is being used as a lock/semaphore and in practice this seems to result in very hard to digest patterns.
juandopazo commentedon Dec 2, 2013
Same here. I haven't found it hard to digest in the cases I ran into, but it's definitely not a good idea.
erights commentedon Dec 2, 2013
Hi Stefan, could you give an example of using a deferred as a
lock/semaphore? Thanks.
On Mon, Dec 2, 2013 at 7:57 AM, Stefan Penner notifications@github.comwrote:
Text by me above is hereby placed in the public domain
Cheers,
--MarkM
juandopazo commentedon Dec 2, 2013
@erights I recently saw something like this:
vvo commentedon Nov 11, 2014
@petkaantonov Hi, is this still considered as an anti-pattern to use deferreds as observers?
Or is this only taste?
How would you implement this otherwise in a nice manner?
Thanks.
benjamingr commentedon Nov 11, 2014
@vvo why the extra layer for
onReady
?vvo commentedon Nov 11, 2014
Was for the example, did not wanted to expose the underlying implementation (promise).
So that, you want to change the implementation with say, array of callbacks, you can.
Also I do not want the API consumer to use the _promise.
benjamingr commentedon Nov 11, 2014
Why would you not want to expose the fact it's a promise? A promise is generic.
You can always do:
pending.ready = pending.ready.then.bind(pending);
but I really don't see the point.vvo commentedon Nov 11, 2014
@benjamingr it's only encapsulation, we are missing the point of the deferred anti-pattern here :) was just an example.
benjamingr commentedon Nov 11, 2014
I'm trying to understand your use case here - why do you need a deferred in the first place?
The deferred anti pattern is about creating an excess deferred for wrapping an existing promise in another promise where
.then
can be used instead. If you're creating a promise based on a callback API likesetTimeout
and automatic promisification facilities are unavailable - you have to use a deferred or the promise constructor.vvo commentedon Nov 11, 2014
I am using Promise and deferred pattern only to not have to implement myself an array of callbacks + ready flag condition + foreach callback. I do not wrap an existing promise.
The way the example is written is only to be able to hide the implementation of my observer object. Like a lot of objects say in Node.js core are "hiding" (_prefixing) some properties. This is a completely different subject.
I only wanted to show how deferred can be used to solve some problems and that it's not always an antipattern.
benjamingr commentedon Nov 11, 2014
If you're not wrapping another promise than you are not doing the deferred anti-pattern, deferred is not an anti-pattern itself..
While I don't think your use is particularly good - it׳s not related to what Petka's article discusses.
vvo commentedon Nov 11, 2014
So you would implement this using an array of callbacks right?
benjamingr commentedon Dec 29, 2020
So, not to stir up an old discussion but deno is using Deferreds and when I raised the issue of throw safety it looks like they are using them like locks.
@stefanpenner asked about using promises as semaphores and @erights asked for an example but I don't actually see a conclusion of what's the "better" way to do it.
Would appreciate some guidance/ideas/thoughts.