Read more

JavaScript: How to query the state of a Promise

Henning Koch
August 05, 2017Software engineer at makandra GmbH

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

Illustration online protection

Rails professionals since 2007

Our laser focus on a single technology has made us a leader in this space. Need help?

  • We build a solid first version of your product
  • We train your development team
  • We rescue your project in trouble
Read more Show archive.org snapshot

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
August 05, 2017Software engineer at makandra GmbH
Posted by Henning Koch to makandra dev (2017-08-05 16:21)