How to check if a Javascript promise has been fulfilled, rejected or resolved

How to check if a Javascript promise has been fulfilled, rejected or resolved

A promise represents the eventual result of an asynchronous operation. The primary way of interacting with a promise is through its then method, which registers callbacks to receive either a promise’s eventual value or the reason why the promise cannot be fulfilled. In some cases, you may want to check the status of the promise. The first you would probably do, is to check if the Promise object has some properties that provide this information, and for your surprise, it doesn't.

If you dump a promise in the console, you will see that it will show 2 "properties" PromiseStatus and PromiseValue:

Javascript Promise status

However, if you try to access those properties with Javascript, you'll see that these values are undefined.

Workaround

As in the original specifications of the Promises API, there's no standard way of accessing the internal state of a promise, you can still workaround this by creating a very simple wrapper that will modify a Promise and will add some useful methods.

The following wrapper is based in the answer of this question in Stack Overflow. The function expects the promise that needs to be modified, then it will return a modified promise with 3 extra methods, isPending, isRejected and isFulfilled. Before start working with this workaround, we want to explain you of a simple way the concept of all the states of a promise. A promise must be in one of these 3 states:

Fulfilled

Fulfilled is a state of a Promise. It means that the promise has been resolved and now has its resolved value (using the internal resolve function). The operation represented by the promise has been completed successfully.

Rejected

Rejected means that the promise has been rejected and now has its rejected reason (using the internal reject function). 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).

Pending

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

Knowing that, let's get started:

/**
 * This function allow you to modify a JS Promise by adding some status properties.
 * Based on: http://stackoverflow.com/questions/21485545/is-there-a-way-to-tell-if-an-es6-promise-is-fulfilled-rejected-resolved
 * But modified according to the specs of promises : https://promisesaplus.com/
 */
function MakeQuerablePromise(promise) {
    // Don't modify any promise that has been already modified.
    if (promise.isResolved) return promise;

    // Set initial state
    var isPending = true;
    var isRejected = false;
    var isFulfilled = false;

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

    result.isFulfilled = function() { return isFulfilled; };
    result.isPending = function() { return isPending; };
    result.isRejected = function() { return isRejected; };
    return result;
}

Remember that the method returns the promise that you provided as first parameter, but modified.

Usage

To understand how the MakeQuerablePromise method works, analize the following example:

// Your promise won't cast the .then function but the returned by MakeQuerablePromise
var originalPromise = new Promise(function(resolve,reject){
    setTimeout(function(){
        resolve("Yeah !");
    },10000);
});

var myPromise = MakeQuerablePromise(originalPromise);

console.log("Initial fulfilled:", myPromise.isFulfilled());//false
console.log("Initial rejected:", myPromise.isRejected());//false
console.log("Initial pending:", myPromise.isPending());//true

myPromise.then(function(data){
    console.log(data); // "Yeah !"
    console.log("Final fulfilled:", myPromise.isFulfilled());//true
    console.log("Final rejected:", myPromise.isRejected());//false
    console.log("Final pending:", myPromise.isPending());//false
});

If you don't want to create an extra variable for your original promise, then provide your promise directly as first parameter:

var myPromise = MakeQuerablePromise(new Promise(function(resolve,reject){
    setTimeout(function(){
        resolve("Yeah !");
    },10000);
}));

console.log("Initial fulfilled:", myPromise.isFulfilled());
console.log("Initial rejected:", myPromise.isRejected());
console.log("Initial pending:", myPromise.isPending());

myPromise.then(function(data){
    console.log(data); // "Yeah !"
    console.log("Final fulfilled:", myPromise.isFulfilled());
    console.log("Final rejected:", myPromise.isRejected());
    console.log("Final pending:", myPromise.isPending());
});

According to the status of the promise, the returned values by the functions will vary and you won't see any changes with the execution of the callbacks of your Promise.

Happy coding !

Become a more social person