Is there a simple and elegant way to determinate if variable is promise or object in javascript (es6)?
I have a variable
let payment;
and at one time in app, it can be either promise or object with real values. I know I can test it it contains some properties like
if (payment.amount)
but this doesn't seems like an elegant solution to me, because properties (data structure) can change in time. Till now I was using
if (typeof payment === 'object')
but I've just figured out, that promises are basically also objects. So this condition is always true.
Is it possible to tell if it's a promise or object with real data?
Check if it has a property then
that is a function:
if(payment != null && typeof payment.then === 'function')
// is a promise
else
// is not a promise
As far as I know, this is the only proper way to check if something is a promise (or a "promise-like" thenable), taking into account all different possible promise implementations.
Don't try to find out. Just make it always a promise.
payment = Promise.resolve(payment);
Promise.resolve
creates a new promise object. If the value passed is itself a promise, the is resolved or rejected when the original one is. If it is anything else, the new promise is resolved immediately with that value.
As with all other native objects, you can use instanceof
with the Promise
constructor:
if (payment instanceof Promise)
However, if you don't know whether it's a native promise or from a custom library, you will usually want to detect a thenable by checking whether it has a .then
method.
But you never really need to distinguish them (other than for debugging purposes). If there is a chance that something is a promise, you will always need to wait for, and construct a promise from it anyway. You don't need to do the distinction yourself, you can just use Promise.resolve
to cast either promise, thenable or plain object to a promise of your favoured implementation - that's how Promise interoperability was designed in the first place, so it will absolutely work.
const promise = Promise.resolve(payment).then(value => {
// value: always a plain value
}); // promise: always a promise
payment instanceof Promise
or this:
payment.constructor.toString().indexOf('Promise') > -1
payment.constructor === Promise