ES6 - decide if object or promise

2019-07-31 13:32发布

问题:

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?

回答1:

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.



回答2:

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.



回答3:

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


回答4:

payment instanceof Promise

or this:

payment.constructor.toString().indexOf('Promise') > -1


回答5:

payment.constructor === Promise