How do I tell if an object is a Promise?

Whether it's an ES6 Promise or a bluebird Promise, Q Promise, etc.

How do I test to see if a given object is a Promise?


How a promise library decides

If it has a .then function - that's the only standard promise libraries use.

The Promises/A+ specification has a notion called thenable which is basically "an object with a then method". Promises will and should assimilate anything with a then method. All of the promise implementation you've mentioned do this.

If we look at the specification:

2.3.3.3 if then is a function, call it with x as this, first argument resolvePromise, and second argument rejectPromise

It also explains the rationale for this design decision:

This treatment of thenables allows promise implementations to interoperate, as long as they expose a Promises/A+-compliant then method. It also allows Promises/A+ implementations to “assimilate” nonconformant implementations with reasonable then methods.

How you should decide

You shouldn't - instead call Promise.resolve(x) (Q(x) in Q) that will always convert any value or external thenable into a trusted promise. It is safer and easier than performing these checks yourself.

really need to be sure?

You can always run it through the test suite :D


Checking if something is promise unnecessarily complicates the code, just use Promise.resolve

Promise.resolve(valueOrPromiseItDoesntMatter).then(function(value) {

})

Disclaimer: not a good answer to updated OP, is per-library, and won't work across realms. Check for .then instead.

This answer, based on the spec is a way to test for a promise that works only sometimes, FYI.

Promise.resolve(obj) == obj &&
BLUEBIRD.resolve(obj) == obj

When this works it's because the algorithm explicitly demands that Promise.resolve must return the exact object passed in if and only if it is a promise created by this constructor.


Disclaimer: not a good answer to updated OP, works for native only, and not across realms. Follow accepted answer instead.

obj instanceof Promise

should do it. Note that this may only work reliably with native es6 promises.

If you're using a shim, a promise library or anything else pretending to be promise-like, then it may be more appropriate to test for a "thenable" (anything with a .then method), as shown in other answers here.


if (typeof thing?.then === 'function') {
    // probably a promise
} else {
    // definitely not a promise
}