JavaScript: How to query the state of a Promise

Updated . Posted . Visible to the public.

Native promises Show archive.org snapshot have no methods to inspect their state.

You can use the promiseState function below to check whether a promise is fulfilled, rejected or still pending:

promiseState(promise, function(state) {
  // `state` now either "pending", "fulfilled" or "rejected"
});

Note that the callback passed to promiseState will be called asynchronously in the next microtask Show archive.org snapshot .

Usage example: Tests

Note

Since this card was written Jasmine has implemented asynchronous matchers Show archive.org snapshot that let you expect a promise's state.

In most of your work with promises, you won't need to inspect its internal state. It is usually sufficient to use the then() function. Where promiseState() becomes useful is when writing unit tests for a function that returns a promise.

Let's say we write a promise-based variant of setTimeout():

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

We would use it like this:

setTimer(300).then(function() { ... ))

Here is a test for setTimer() that uses promiseState():

describe('setTimer()', function() {
  it('returns a promise that is resolved after the given delay', function(done) {
  
    promise = setTimer(300)

    promiseState(promise, function(state) {
      expect(state).toEqual('pending')
    ))

    setTimout(function() {
      promiseState(promise, function(state) {
        expect(state).toEqual('fulfilled');
        done();
      });
    }, 300);  
    
  });
})

Implementation of promiseState

Here is the promiseState function:

function promiseState(promise, callback) {
  // Symbols and RegExps are never content-equal
  var uniqueValue = window['Symbol'] ? Symbol('unique') : /unique/

  function notifyPendingOrResolved(value) {
    if (value === uniqueValue) {
      return callback('pending')
    } else {
      return callback('fulfilled')
    }
  }

  function notifyRejected(reason) {
    return callback('rejected')
  }
  
  var race = [promise, Promise.resolve(uniqueValue)]
  Promise.race(race).then(notifyPendingOrResolved, notifyRejected)
}

Promise.race takes an array of promises and returns a promise that settles (fulfills or rejects) like the first settled promise.

If it resolves to our unique value, we know that promise is still pending.

Henning Koch
Last edit
Henning Koch
License
Source code in this card is licensed under the MIT License.
Posted by Henning Koch to makandra dev (2017-08-05 14:21)