67

I'm used to Dojo promises, where I can just do the following:

promise.isFulfilled();
promise.isResolved();
promise.isRejected();

Is there a way to determine if an ES6 promise is fulfilled, resolved, or rejected? If not, is there a way to fill in that functionality using Object.defineProperty(Promise.prototype, ...)?

knpwrs
  • 15,691
  • 12
  • 62
  • 103
  • If I'm not mistaken you should be able to access the state and resolve value https://people.mozilla.org/~jorendorff/es6-draft.html#sec-properties-of-promise-instances – megawac Jan 31 '14 at 17:07
  • 1
    The intent of internal slots, of the form `[[]]` is there is no way to access them as they are specification details that might not actually exist in the implementation. They are used to describe the behavior of the spec, not the runtime layout of the actual object; so, no you can't access the internal state. – chuckj Jan 31 '14 at 20:43
  • 4
    Why was this question marked a duplicate? This is the question with the better actual response. The other just tells you what you can't do and doesn't provide any hint as to a solution. I think the other question/answer is useless for actually solving the posed problem. – Akrikos Aug 10 '18 at 18:57

1 Answers1

65

They are not part of the specification nor is there a standard way of accessing them that you could use to get the internal state of the promise to construct a polyfill. However, you can convert any standard promise into one that has these values by creating a wrapper,

function MakeQueryablePromise(promise) {
    // Don't create a wrapper for promises that can already be queried.
    if (promise.isResolved) return promise;
    
    var isResolved = false;
    var isRejected = false;

    // Observe the promise, saving the fulfillment in a closure scope.
    var result = promise.then(
       function(v) { isResolved = true; return v; }, 
       function(e) { isRejected = true; throw e; });
    result.isFulfilled = function() { return isResolved || isRejected; };
    result.isResolved = function() { return isResolved; }
    result.isRejected = function() { return isRejected; }
    return result;
}

This doesn't affect all promises, as modifying the prototype would, but it does allow you to convert a promise into a promise that exposes it state.

Won Jun Bae
  • 5,140
  • 6
  • 43
  • 49
chuckj
  • 27,773
  • 7
  • 53
  • 49
  • 2
    This seems to be wrong. Your implementation returns false for isResolved when promise is rejected. I would set isFulfilled in the fulfill callback and then calculate isResolved based on either isFulfilled or isRejected being set. However the simplest way is to set isResolved in both callbacks alongside respective isFulfilled and isRejected values. – op1ekun Feb 26 '15 at 13:57
  • I believe the implementation, as far as it goes, is correct, at least according to the dojo documentation: http://dojotoolkit.org/reference-guide/1.10/dojo/promise/Promise.html – chuckj Mar 11 '15 at 21:49
  • 6
    Indeed your [terminology](http://stackoverflow.com/q/29268569/1048572) seems to be messed up. You should use `isSettled`, `isFulfilled` and `isRejected`. – Bergi May 10 '16 at 17:59
  • 2
    The question is about simulating Dojo with a standard promise and the terminology is theirs, not mine. – chuckj May 24 '16 at 00:13
  • 2
    This always returns false for me in all of the 3 functions... – shinzou Jun 11 '17 at 11:33
  • 6
    Note that this will not work synchronously, not even for already resolved promises. E.g., `console.log(MakeQuerablePromise(Promise.resolve(777)).isResolved())` gives `false`. – Remirror Dec 10 '20 at 14:43