探究如何判断一个值是Promise
文章目录
- 前言
- 直接上方法
- 方法一:instanceOf
- 方法二:直接判断是否有 then
- 方法三:不需要判断
- 方法四:Object.prototype.toString.call()
- 方法五:Symbol.toStringTag 属性
- 特殊情况
前言
虽然在开发中很少的场景下需要判断一个值,是否是promise,但是遇到的时候还真无从下手。下面就讲解一下各种判断方法。
Promise基本使用方法就跳过了,网上很容易查到。
直接上方法
方法一:instanceOf
instanceOf 定义:
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
示例:
const p = Promise.resolve(1)p instanceof Promisep.__proto__ === Promise.prototype // true
因为 p 的 proto 指向 Promise.prototype,所以原理上使用 instanceOf 是可行的。
特殊情况:就是三方封装的Promise,只要符合 ES6 对 Promise/A+ 规范就行,比如 bluebird。
import { Promise as BluebirdPromise } from 'bluebird'
const test = new BluebirdPromise((resolve) => resolve('success'))
console.log(test instanceof Promise) // 输出为 false
console.log(test instanceof BluebirdPromise ) // 输出为 true
方法二:直接判断是否有 then
如果不能用 instanceOf 判断的话,是否用 then 可以
示例:
const p = Promise.resolve(1)
if (p !== null &&(typeof p === 'object' || typeof p === 'function') &&typeof p.then === 'function'
) {// 那么这个值为 thenable
}
特殊情况:比如一个对象中恰好定义了一个 then 函数,但其并不是表示 Promise 或者 thenable。
class Test {then() {console.log('不是promise')}
}
方法三:不需要判断
如果手写过promise方法的实现,可以发现并没有去做判断,一个值是不是promise
而是直接使用:
例如实现race
Promise.race = function (promises) {return new Promise((resolve, reject) => {for (let i = 0; i < promises.length; i++) {Promise.resolve(promises[i]).then(resolve).catch(reject)}})
}
可以发现一行代码Promise.resolve(promises[i]).then(resolve).catch(reject)
,这里的意思是,不管你传入的数组元素是否是promise都直接用promise.resolve包一层,这样就可以不用去判断是不是promise。
方法四:Object.prototype.toString.call()
Object.prototype.toString.call() 方法返回一个对象的类型字符串。对于 Promise 对象,返回字符串为 “[object Promise]”:
if (Object.prototype.toString.call(object) === '[object Promise]') {// object 是一个 Promise 对象
}
缺点:和方法一一样,第三方实现的promise可能无法判断,并且这个返回值也是可以被修改的。
方法五:Symbol.toStringTag 属性
ES2015 引入了 Symbol.toStringTag 属性,允许对象指定自己的类型字符串。Promise 对象的 Symbol.toStringTag 属性值为 “Promise”:
if (object[Symbol.toStringTag] === 'Promise') {// object 是一个 Promise 对象
}
缺点:和方法一一样,第三方实现的promise可能无法判断,并且这个返回值也是可以被修改的。
特殊情况
如果真的遇到了必须要判断一个值是不是promise的时候,可以用上面的方法配合使用