Promise
,还是 Bluebird 的 Promise
、Q 的 Promise
等等。我该如何测试一个给定的对象是否为
Promise
?Promise
,还是 Bluebird 的 Promise
、Q 的 Promise
等等。Promise
?如果它有一个.then
函数 - 这是标准的Promise库使用的 唯一 方法。
Promise/A+规范中有一个叫做then
able的概念,它基本上是“具有then
方法的对象”。Promise将并且应该同化任何具有then方法的东西。你提到的所有Promise实现都这样做。
如果我们查看规范:
2.3.3.3 如果
then
是一个函数,则使用x作为this,第一个参数resolvePromise,第二个参数rejectPromise来调用它
它还解释了这个设计决策的原因:
这种对于
then
able的处理方式允许Promise实现进行互操作,只要它们公开符合Promises/A+的then
方法即可。它还允许Promises/A+实现通过合理的then
方法“同化”不符合规定的实现。
你不应该 - 相反,调用Promise.resolve(x)
(在Q中调用Q(x)
),它将 始终 将任何值或外部thenable转换为可信赖的Promise。这比自己执行这些检查更安全和更容易。
你总是可以通过测试套件来验证 :D
Promise.resolve
会自动为您处理这个问题 - 您始终会获得一个Promise。 - Benjamin GruenbaumPromise.resolve(a_promise)
会返回 a_promise
呢? - Onkeltemasync
上下文中,await thing
会使其解析为thing
的值或其承诺值。 - Onkeltem检查某些内容是否为 Promise 会使代码变得不必要的复杂,只需使用 Promise.resolve
Promise.resolve(valueOrPromiseItDoesntMatter).then(function(value) {
})
===
代替==
呢? - Neil S免责声明:这不是对更新后的OP的好答案,仅适用于本地使用,不能跨越领域。请按照被接受的答案进行操作。
obj instanceof Promise
应该这样做。请注意,这可能仅在使用本地es6承诺时可靠工作。
如果您正在使用模拟器、承诺库或任何其他类似于承诺的东西,则更适合测试一个“thenable”(具有.then
方法的任何内容),如此处的其他答案所示。
obj && typeof obj.then == 'function'
,因为它适用于所有类型的 promises,并且实际上是规范推荐并被实现和填充物使用的方式。例如,原生的 Promise.all
将适用于所有的 then
ables,不仅仅是其他原生 promises。所以你的代码也应该如此。因此,instanceof Promise
不是一个好的解决方案。 - Stijn de Wittconsole.log(typeof p, p, p instanceof Promise);
产生了这样的输出:object Promise { <pending> } false
。正如您所看到的,它确实是一个 Promise - 但是 instanceof Promise
测试返回了 false
? - Mörreif (typeof thing?.then === 'function') {
// probably a promise
} else {
// definitely not a promise
}
thing && ...
来防范它。 - mrBornathing?.then
中的 ?
处理了对未定义变量的检查。这被称为“可选链”。阅读更多信息:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Optional_chaining - Ajay Guptaif (p && 'then' in p && typeof p.then === 'function')
- Jonathan要判断给定的对象是否为ES6 Promise,我们可以使用以下谓词:
function isPromise(p) {
return p && Object.prototype.toString.call(p) === "[object Promise]";
}
Call
直接从Object.prototype
调用toString
会返回给定对象类型的本机字符串表示,在我们的例子中是"[object Promise]"
。这确保了给定对象
toString
方法。instanceof
或isPrototypeOf
相比。Symbol.toStringTag
进行 标记修改,都可以返回"[object Promise]"
。这可能是预期的结果,也可能取决于项目情况(例如,如果存在自定义 Promise 实现)。
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
}
"function Identifier ( FormalParameterListopt ) { FunctionBody }"
上述内容已得到相应处理。在所有主流浏览器中,FunctionBody均为[native code]
。
MDN:Function.prototype.toString
这也适用于多个环境上下文。
这是 graphql-js 包检测 promises 的方法:
function isPromise(value) {
return Boolean(value && typeof value.then === 'function');
}
value
是您的函数返回的值。我在我的项目中使用了这段代码,到目前为止还没有问题。
虽然不是对整个问题的回答,但我认为值得提一下,在Node.js 10中添加了一个名为isPromise
的新实用程序函数,用于检查对象是否为原生Promise:
const utilTypes = require('util').types
const b_Promise = require('bluebird')
utilTypes.isPromise(Promise.resolve(5)) // true
utilTypes.isPromise(b_Promise.resolve(5)) // false
async myMethod(promiseOrNot){
const theValue = await promiseOrNot()
}
Promise.resolve()
。 - Felix K.这里是来自https://github.com/ssnau/xkit/blob/master/util/is-promise.js的代码:
!!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function';
如果一个对象有一个then
方法,它应该被视为一个Promise
。
.then
方法,但这并不能确定你得到的是一个 Promise。此时你所知道的只是该对象具有类似 Promise 的.then
方法。 - Scott Offen.then
方法的对象,但这并不意味着它是Promise,也不会像Promise一样运作,并且可能根本没想过要像Promise一样使用它。检查是否存在.then
方法只能告诉你如果对象没有.then
方法,则你没有Promise。相反,存在.then
方法并不一定意味着你有Promise。 - Scott Offen.then
方法。是的,这种方法可能会出现误判,但所有的Promise库都依赖于这种假设(因为它们只能依赖于这个)。我所能想到的唯一替代方案是采用Benjamin Gruenbaum提出的建议并将其运行通过Promise测试套件。但对于实际的生产代码来说,这不太实际。 - JLRisheconst isPromise = v => typeof v === 'object' && typeof v.then === 'function'
可以翻译为“判断变量是否为 Promise 的函数,判断依据是变量的类型为对象并且具有 then 方法”。 - Dominic