How do I tell if an object is a Promise?

JavascriptPromiseQBluebirdEs6 Promise

Javascript Problem Overview


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?

Javascript Solutions


Solution 1 - Javascript

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

Solution 2 - Javascript

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

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

Solution 3 - Javascript

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.

Solution 4 - Javascript

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.

Solution 5 - Javascript

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

Solution 6 - Javascript

To see if the given object is a ES6 Promise, we can make use of this predicate:

function isPromise(p) {
  return p && Object.prototype.toString.call(p) === "[object Promise]";
}

Calling toString directly from the Object.prototype returns a native string representation of the given object type which is "[object Promise]" in our case. This ensures that the given object

  • Bypasses false positives such as..:
    • Self-defined object type with the same constructor name ("Promise").
    • Self-written toString method of the given object.
  • Works across multiple environment contexts (e.g. iframes) in contrast to instanceof or isPrototypeOf.

However, any particular host object, that has its tag modified via Symbol.toStringTag, can return "[object Promise]". This may be the intended result or not depending on the project (e.g. if there is a custom Promise implementation).


To see if the object is from a native ES6 Promise, we can use:

function isNativePromise(p) {
  return p && typeof p.constructor === "function"
    && Function.prototype.toString.call(p.constructor).replace(/\(.*\)/, "()")
    === Function.prototype.toString.call(/*native object*/Function)
      .replace("Function", "Promise") // replacing Identifier
      .replace(/\(.*\)/, "()"); // removing possible FormalParameterList 
}

According to this and this section of the spec, the string representation of function should be:

> "function Identifier ( FormalParameterListopt ) { FunctionBody }"

which is handled accordingly above. The FunctionBody is [native code] in all major browsers.

MDN: Function.prototype.toString

This works across multiple environment contexts as well.

Solution 7 - Javascript

This is how graphql-js package detects promises:

function isPromise(value) {
  return Boolean(value && typeof value.then === 'function');
}

value is the returned value of your function. I'm using this code in my project and have no problem so far.

Solution 8 - Javascript

Not an answer to the full question but I think it's worth to mention that in Node.js 10 a new util function called isPromise was added which checks if an object is a native Promise or not:

const utilTypes = require('util').types
const b_Promise = require('bluebird')

utilTypes.isPromise(Promise.resolve(5)) // true
utilTypes.isPromise(b_Promise.resolve(5)) // false

Solution 9 - Javascript

If you are in an async method you can do this and avoid any ambiguity.

async myMethod(promiseOrNot){
  const theValue = await promiseOrNot()
}

If the function returns promise, it will await and return with the resolved value. If the function returns a value, it will be treated as resolved.

If the function does not return a promise today, but tomorrow returns one or is declared async, you will be future-proof.

Solution 10 - Javascript

Here is the code form https://github.com/ssnau/xkit/blob/master/util/is-promise.js

!!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function';

if an object with a then method, it should be treat as a Promise.

Solution 11 - Javascript

In case you are using Typescript, I'd like to add that you can use the "type predicate" feature. Just should wrap the logical verification in a function that returns x is Promise<any> and you won't need to do typecasts. Below on my example, c is either a promise or one of my types which I want to convert into a promise by calling the c.fetch() method.

export function toPromise(c: Container<any> | Promise<any>): Promise<any> {
    if (c == null) return Promise.resolve();
    return isContainer(c) ? c.fetch() : c;
}

export function isContainer(val: Container<any> | Promise<any>): val is Container<any> {
    return val && (<Container<any>>val).fetch !== undefined;
}

export function isPromise(val: Container<any> | Promise<any>): val is Promise<any> {
    return val && (<Promise<any>>val).then !== undefined;
}

More info: https://www.typescriptlang.org/docs/handbook/advanced-types.html

Solution 12 - Javascript

after searching for a reliable way to detect Async functions or even Promises, i ended up using the following test :

() => fn.constructor.name === 'Promise' || fn.constructor.name === 'AsyncFunction'

Solution 13 - Javascript

Anything that pushes a possibly synch value into Promise.resolve(value) for the comfort of avoiding comparison turns your code into an otherwise avoidable async. Sometimes you don't want it at that stage. You want to know the result evaluated right before some earlier resolution in the microtask queue bites you right..?

One can possibly do like;

var isPromise = x => Object(x).constructor === Promise;

I checked it against some edge cases that i can think of and it seems to work.

isPromise(undefined);                                           // <- false
isPromise(null);                                                // <- false
isPromise(0);                                                   // <- false
isPromise("");                                                  // <- false
isPromise({});                                                  // <- false
isPromise(setTimeout);                                          // <- false
isPromise(Promise);                                             // <- false
isPromise(new Promise((v,x) => setTimeout(v,1000,"whatever"))); // <- true
isPromise(fetch('http://example.com/movies.json'));             // <- true

I haven't checked it up against any non-native librarires but what's the point now?

Solution 14 - Javascript

it('should return a promise', function() {
    var result = testedFunctionThatReturnsPromise();
    expect(result).toBeDefined();
    // 3 slightly different ways of verifying a promise
    expect(typeof result.then).toBe('function');
    expect(result instanceof Promise).toBe(true);
    expect(result).toBe(Promise.resolve(result));
});

Solution 15 - Javascript

I use this function as a universal solution:

function isPromise(value) {
  return value && value.then && typeof value.then === 'function';
}

Solution 16 - Javascript

const isPromise = (value) => {
  return !!(
    value &&
    value.then &&
    typeof value.then === 'function' &&
    value?.constructor?.name === 'Promise'
  )
}

As for me - this check is better, try it out

Solution 17 - Javascript

In Angular:

import { isPromise } from '@angular/compiler/src/util';

if (isPromise(variable)) {
  // do something
}

J

Solution 18 - Javascript

use this library

https://www.npmjs.com/package/is-promise

import isPromise from 'is-promise';
 
isPromise(Promise.resolve());//=>true
isPromise({then:function () {...}});//=>true
isPromise(null);//=>false
isPromise({});//=>false
isPromise({then: true})//=>false

Solution 19 - Javascript

ES6:

const promise = new Promise(resolve => resolve('olá'));

console.log(promise.toString().includes('Promise')); //true

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiontheramView Question on Stackoverflow
Solution 1 - JavascriptBenjamin GruenbaumView Answer on Stackoverflow
Solution 2 - JavascriptEsailijaView Answer on Stackoverflow
Solution 3 - JavascriptjibView Answer on Stackoverflow
Solution 4 - JavascriptjibView Answer on Stackoverflow
Solution 5 - JavascriptunobfView Answer on Stackoverflow
Solution 6 - JavascriptBoghyon HoffmannView Answer on Stackoverflow
Solution 7 - JavascriptmuratgozelView Answer on Stackoverflow
Solution 8 - JavascriptLEQADAView Answer on Stackoverflow
Solution 9 - JavascriptSteven SpunginView Answer on Stackoverflow
Solution 10 - JavascriptssnauView Answer on Stackoverflow
Solution 11 - JavascriptMurilo PerroneView Answer on Stackoverflow
Solution 12 - JavascriptSebastien H.View Answer on Stackoverflow
Solution 13 - JavascriptReduView Answer on Stackoverflow
Solution 14 - JavascriptpurplecabbageView Answer on Stackoverflow
Solution 15 - JavascriptsafrazikView Answer on Stackoverflow
Solution 16 - JavascriptDZMITRY ASTRAUKHView Answer on Stackoverflow
Solution 17 - JavascriptJonathanView Answer on Stackoverflow
Solution 18 - JavascripttylimView Answer on Stackoverflow
Solution 19 - JavascriptMathias Gheno AzzoliniView Answer on Stackoverflow