24

I'm getting confused with the different terminology thrown around. From my understanding, a promise can be:

  • fulfilled
  • rejected
  • pending
  • settled
  • resolved
  • defer

Does resolved mean settled? Or does it mean it’s fulfilled? And what the heck is defer?

user3840170
  • 26,597
  • 4
  • 30
  • 62
awaken
  • 789
  • 1
  • 11
  • 22
  • 2
    Unfortunately, this terminology is not used consistently. In particular, way too many people use "resolved" to mean "fulfilled". You may find this useful: http://stackoverflow.com/questions/18280375/q-js-difference-between-resolve-and-fulfill/18295163#18295163 –  Mar 26 '15 at 02:42
  • 2
    A perfect opportunity for applying the word "renege" was wasted when selecting these terms. – Magnus Lind Oxlund Mar 16 '19 at 10:23

3 Answers3

67

Terminology can be hard.
Let's take from the Promises/A+ specification and the respective ES6 section that there are 3 states:

  • pending - the promise has not taken a value yet, its outcome is still uncertain.
  • fulfilled - the promise successfully got a result value "assigned"
  • rejected - the promise is given a reason why no result could be acquired, typically an error.

The term settled is a hyperonym for fulfilled and rejected, meaning either - the opposite of pending.

The dynamic verbs fulfill and reject describe changing the state from pending into either the fulfilled or rejected. These transitions are called fulfillment or rejection of the promise.

Those were easy. Now, resolve is a different beast. It sometimes is used synonymous to "fulfill", but it would better be understood as settling the promise's fate to either fulfilled or rejected. The resolution (seldom: settlement) of a promise means that it leaves the pending state. But not even that is accurate - the problem is the recursive nature of the Promise Resolution Procedure:

  • resolving a promise with a "plain" value means fulfilling it

  • resolving a promise with a promise (or thenable) means adopting its state:

    • resolving with a fulfilled promise is a fulfillment
    • resolving with a rejected promise is a rejection
    • resolving with a pending promise means waiting for its resolution

Yes, if a promise is resolved it might not even be known whether it's going to be fulfilled or rejected. But it means the fate is no longer undetermined, as it's bound to the promise that we resolved with - notice that you can resolve a promise only once, it cannot be resolved to a different value (by calling resolve/reject again).

Ignoring this special case, a resolved promise usually means a settled promise.

Or, to cite the ECMAScript 6 Specification:

A promise is resolved if it is settled or if it has been “locked in” to match the state of another promise. Attempting to resolve or reject a resolved promise has no effect. A promise is unresolved if it is not resolved. An unresolved promise is always in the pending state. A resolved promise may be pending, fulfilled or rejected.

state diagram with transitions


and what the heck is defer?

Deferring a result means that you return an (asynchronous) promise for the result, and not the result directly (synchronously). And also return a deferred rejection instead of throwing synchronously.

Notice that "defer" is also used in some libraries (Q) as the method name to construct a Deferred object - see this answer on The differences between Deferred, Promise and Future for a good explanation.
Oh, and never trust variable names: defer might as well be an abbreviated "deferredObject".

Nick McCurdy
  • 17,658
  • 5
  • 50
  • 82
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 2
    typo: hyperonym → hypernym – kYuZz Aug 30 '15 at 13:50
  • 1
    A+ for that visual – indigo Jul 12 '16 at 23:16
  • Also known as "preaching in the wilderness". –  Sep 04 '16 at 15:21
  • 2
    The visual is very helpful, but would be more so if it were made clear that "pending" includes the part of "resolved" that is not included in "settled". As it is, it gives the impression that "pending" and "resolved" are mutually exclusive, contrary to the quote from the ECMA spec. – LarsH Feb 01 '17 at 19:23
  • Great answer. The key is to understand the difference between "resolve" and "settle". As per the spec: "A promise is resolved if it is settled **or if it has been “locked in” to match the state of another promise**". Note that the other promise might still be pending (not settled). I like to think as "resolved" = "settled+" (pun on Promise/A+). – mdcq May 03 '21 at 23:11
  • 1
    What might be confusing is that in most cases "resolve" only means means "**fulfill** or match state of another promise". E.g. for a non-thenable value, `Promise.resolve(..)` or `new Promise((resolve, _) => {resolve(..)})` only ever create a fulfilled promise, but never a rejected one. However, for the unusual case of a non-promise thenable, it could reject or fulfill (i.e. settle). Therefore "settle or match state of another promise" is actually correct. – mdcq May 04 '21 at 00:28
  • hi @Bergi +1 , that means that **all** promises are *resolved*, once they are *resolved*, they will take a *rejected* or *fulfilled* status, right? –  Mar 11 '23 at 01:23
  • That is, they all go through the "state" resolved @Bergi –  Mar 11 '23 at 01:24
  • 1
    @GeorgeMeijer No. You can resolve a promise with another never-resolving promise, then it won't settle (reject or fulfill) either. – Bergi Mar 11 '23 at 01:25
  • Excellent @Bergi +1, I didn't know that case. For example, if I use `Promise.resolve('a value')` the promise is resolved, but there it can already take the rejected or fulfilled state, i.e. nothing prevents that it can still be rejected, right? –  Mar 11 '23 at 01:30
  • 1
    @GeorgeMeijer If you resolve a promise with a string, it's immediately fulfilled with that string. It won't ever be rejected. It's only that when you resolve a promise with another promise (or thenable) that its eventual fate might not be known. – Bergi Mar 11 '23 at 01:34
  • Thanks @Bergi, `Promise.resolve()` had me confused. One last question, so, `Promise.reject()` with a value other than a promise will always be rejected , right? –  Mar 11 '23 at 01:42
  • i.e., it applies the same as Promise.resolve() but for rejected state @Bergi –  Mar 11 '23 at 01:44
  • 1
    Actually no, `Promise.reject()` *always* returns a rejected promise, not matter what value you pass in. Even a promise - you can reject a promise with a promise. You shouldn't ever do that, it's weird, but it's possible. – Bergi Mar 11 '23 at 02:10
  • hi @Bergi +1. "*resolving a promise with a "plain" value means fulfilling it*" - That case is when it resolves to something other than a promise object, right? –  Mar 11 '23 at 13:37
  • 1
    Yes, "plain" means "non-thenable"/"non-promise" there. – Bergi Mar 11 '23 at 14:05
  • "*Ignoring this special case, a resolved promise usually means a settled promise.*" - Thanks @Bergi, so this quote refers to when the promise resolved to something other than non-thenable/non-promise, right? –  Mar 11 '23 at 14:13
  • 1
    @Coder23 Yes. A resolved promise literally is just one whose `resolve`r function has been called. – Bergi Mar 11 '23 at 21:24
13

The three promise states are listed in section 2.1 of the Promises/A+ specification.

From the specification:

enter image description here

So here are each of the terms you asked about:

Pending is the initial promise state. The operation represented by the promise has not yet been filfilled or rejected.

Fulfilled is another of the three promise states. It means that the promise has been resolved and now has its resolved value. The operation represented by the promise has been completed successfully.

Rejected is another of the three promise states. It means that the promise has been rejected and now has its rejected reason. The operation represented by the promise failed to obtain a value and thus has a reason for failing to do so (typically an error code or error object, but it can be anything).

Settled is a term that means the promise is either fulfilled or rejected (e.g. it's not pending any more), but it is not a separate state just a descriptive term to indicate it is no longer pending.

Resolved is a term that is often used to mean the same as fulfilled, but the two are not exactly the same. A promise can be resolved with a value which leads to fulfillment or it can be resolved with a rejected promise (which leads to rejection of this promise) or it can be resolved with a pending promise (which means it will now be waiting on the eventual state of some other promise).

It's hard to say exactly what you mean by defer. Promises are often classified as deferred objects in that they are an object that represents an action and result that is deferred to the future (it will occur in the future). In some promises implementations, there are actually two types of objects, a deferred object and a promise object. The deferred object is a superset of the promise object. Both can observe when the action is resolved or rejected with .then() handlers. But, only the deferred object can actually change the state to resolved or rejected.

In jQuery, you can create a deferred object with $.Deferred(). In other implementations such as ES6 promises, you just have promise objects with a constructor callback that has reject and resolve functions. The world is presumably moving toward what ES6 will have.

jQuery example that uses a deferred object:

function delay(t) {
    var defer = $.Deferred();
    setTimeout(function() {
        defer.resolve();
    }, t);
    return defer.promise()
 }

 delay(200).then(function() {
     // run my delayed function now
     doMyThing();
 });

ES6 promise example:

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

 delay(200).then(function() {
     // run my delayed function now
     doMyThing();
 });
Nick McCurdy
  • 17,658
  • 5
  • 50
  • 82
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • They don't like it when you quote the spec. /s – Millie Smith Mar 26 '15 at 00:01
  • @MillieSmith - yeah as much as I like and use MDN as a useful resource, it seems to have the promise states wrong this time so I thought it wise to go right to the spec. – jfriend00 Mar 26 '15 at 00:15
  • @jfriend00: See my answer to clear up the difference between resolving and fulfilling. Your description isn't inaccurate enough for a downvote, though :-) – Bergi Mar 26 '15 at 01:37
  • @Bergi - OK, I cleaned up some of my description of the terms. – jfriend00 Mar 26 '15 at 02:37
1

Domenic Denicola's "States and Fates" is a good, pithy summary.

States:

  • a promise is fulfilled if promise.then(f) will call f "as soon as possible"
  • a promise is rejected if promise.then(undefined, r) will call r "as soon as possible"
  • a promise is pending if it is neither fulfilled nor rejected.

Fates:

  • a promise is resolved if trying to resolve or reject it has no effect, i.e. the promise has been "locked in" to either follow another promise, or has been fulfilled or rejected
  • a promise is unresolved if it is not resolved, i.e. if trying to resolve or reject it will have an impact on the promise.

Follow the link for details 'relating states and fates'.

ChrisV
  • 8,748
  • 3
  • 48
  • 38