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
:
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.isFulfilled) 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 !