最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - When would someone need to create a deferred? - Stack Overflow

programmeradmin0浏览0评论

It seems generally that creating deferred objects is now monly discouraged in favor of using the ES6-style Promise constructor. Does there exist a situation where it would be necessary (or just better somehow) to use a deferred?

For example, on this page, the following example is given as justification for using a deferred:

function delay(ms) {
    var deferred = Promise.pending();
    setTimeout(function(){
        deferred.resolve();
    }, ms);
    return deferred.promise;
}

However, this could be done just as well with the Promise constructor:

function delay(ms) {
    return new Promise(function(resolve, reject){
        setTimeout(function(){
            resolve();
        }, ms);
    });
}

It seems generally that creating deferred objects is now monly discouraged in favor of using the ES6-style Promise constructor. Does there exist a situation where it would be necessary (or just better somehow) to use a deferred?

For example, on this page, the following example is given as justification for using a deferred:

function delay(ms) {
    var deferred = Promise.pending();
    setTimeout(function(){
        deferred.resolve();
    }, ms);
    return deferred.promise;
}

However, this could be done just as well with the Promise constructor:

function delay(ms) {
    return new Promise(function(resolve, reject){
        setTimeout(function(){
            resolve();
        }, ms);
    });
}
Share Improve this question asked Sep 29, 2015 at 20:22 xyzxyz 1,4972 gold badges13 silver badges18 bronze badges 5
  • The cases where you'd use the promise constructor are pretty rare too. For what it's worth. – Benjamin Gruenbaum Commented Sep 29, 2015 at 21:02
  • As Benjamin Gruenbaum said, you would seldom need to even use new Promise. Your example above is a case in point. A delay promise that resolves to undefined is not very useful. You would typically want to delay an existing promise e.g. somPromise.delay(t).then(...), in which case your delay would not create a new promise. If you need to start a promise chain where you don't have a promise, you can simply use Promise.resolve or Promise.reject – caasjj Commented Sep 29, 2015 at 21:26
  • function() { resolve(); } is equivalent to resolve in this case. – user663031 Commented Sep 30, 2015 at 3:44
  • Possible duplicate of stackoverflow./questions/31069453/… – Roamer-1888 Commented Sep 30, 2015 at 13:39
  • 1 @caasjj That's true for some promise implementations, but not all of them provide a .delay()-type method. ES6 native promises surely don't. – JLRishe Commented Jul 17, 2016 at 6:16
Add a ment  | 

2 Answers 2

Reset to default 7

Does there exist a situation where it would be necessary (or just better somehow) to use a deferred?

There is no such situation where a deferred is necessary. "Better" is a matter of opinion so I won't address that here.

There's a reason that the ES6 promise specification does not have a deferred object. You simply don't need one. Anything that people used to use a deferred object for can always be done another way that doesn't use a deferred object.

First off, the majority of uses fit very nicely into the promise constructor model. Secondly, any other cases that didn't fit quite so cleanly into that model can still be acplished with the promise constructor or by starting with a resolved promise and chaining to it.

The main use case I've seen for a deferred is when you want to pass the ability to resolve() or reject() off to some other piece of code other than the code that created the promise. A Deferred made that very easy since you could just pass the deferred object and it had public methods for resolving or rejecting it. But, with a promise, you can also just pass the resolve and/or reject methods. Since they are bound to the specific object automatically, you can just pass the function references. And, in other cases, you can just let the other code create their own promise and resolve/reject it themselves and have that operation linked to yours rather than letting them resolve/reject your promise. Is all that quite as clean as passing a deferred object? Mostly a matter of opinion, but neither are very mon use cases and all are something that can be acplished without a separate deferred object.

And, as torazaburo points out, letting some external code resolve or reject your promise is a bit of an anti-pattern in its own right. You created the promise - you resolve/reject it. If you want to use external events to decide when to resolve/reject it, then have them notify you (via their own promise or callback) and you can resolve/reject your own promise. Or, have them create their own promise that you can use. That's really the desired model. Or, let them chain onto your promise so that the end result is gated by when their operation is done.

If one was used to coding with the deferred object (say with a jQuery deferred), it might take a little getting used to coding without it, but after a little while you just start to think differently and it starts to e natural to just use the promise constructor.

Once you promisify the sphere of async operations that you use in any given application, it's pretty rare that you ever even need to create your own promises any more because you are mostly just building off promises that the async functions you call are already creating or using flow control operations like Promise.all() which create uber promises for you.

This is the main point of anti-patterns. Use the promises that are already created for you rather than manually create more. Chain them. Return promises from .then() handlers to link async operations under logic control.

Of course, there are existing async operations that don't return promises for which somebody needs to create a promise, but that should be done in a promisify layer somewhere outside the purvey of your main coding logic and done only once for that operation and then code that calls the async operation should be able to just use the returned promises.

Native Promises don't have all the built-in methods that deferred has out of the box, for example the method to resolve the promise outside the scope of its constructor (very easy to implement with native Promise, though), and the ability to look at the status of a promise (which is hidden from regular JavaScript on native Promises, though it can be inspected in the dev tools).

The main reason to use deferred today would be backwards patibility with code that depends on those extra methods. Hard to give a definitive answer to your question without stepping onto opinion territory.

发布评论

评论列表(0)

  1. 暂无评论