Javascript 如何判断一个对象是否是一个 Promise?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27746304/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I tell if an object is a Promise?
提问by theram
Whether it's an ES6 Promise or a bluebird Promise, Q Promise, etc.
无论是 ES6 Promise 还是 bluebird Promise、Q Promise 等。
How do I test to see if a given object is a Promise?
我如何测试一个给定的对象是否是一个 Promise?
回答by Benjamin Gruenbaum
How a promise library decides
承诺库如何决定
If it has a .thenfunction - that's the onlystandard promise libraries use.
如果它有一个.then函数——那是唯一使用的标准承诺库。
The Promises/A+ specification has a notion called thenable which is basically "an object with a thenmethod". Promises will and should assimilate anythingwith a then method. All of the promise implementation you've mentioned do this.
Promises/A+ 规范有一个叫做then能够的概念,它基本上是“一个带有then方法的对象”。Promise 将并且应该使用 then 方法吸收任何东西。你提到的所有承诺实现都是这样做的。
If we look at the specification:
如果我们看一下规范:
2.3.3.3 if
thenis a function, call it with x as this, first argument resolvePromise, and second argument rejectPromise
2.3.3.3 如果
then是一个函数,用 x 作为 this 调用它,第一个参数是 resolvePromise,第二个参数是 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+-compliantthenmethod. It also allows Promises/A+ implementations to “assimilate” nonconformant implementations with reasonable then methods.
这种对能力的处理
then允许 promise 实现互操作,只要它们公开一个 Promises/A+ 兼容的then方法。它还允许 Promises/A+ 实现使用合理的 then 方法“同化”不一致的实现。
How you should decide
你应该如何决定
You shouldn't - instead call Promise.resolve(x)(Q(x)in Q) that will alwaysconvert any value or external thenable into a trusted promise. It is safer and easier than performing these checks yourself.
你不应该 - 而是调用Promise.resolve(x)(Q(x)在 Q 中),它总是将任何值或外部then能力转换为可信的承诺。这比自己执行这些检查更安全、更容易。
reallyneed to be sure?
真的需要确定吗?
You can always run it through the test suite:D
您始终可以通过测试套件运行它:D
回答by Esailija
Checking if something is promise unnecessarily complicates the code, just use Promise.resolve
检查某些东西是否是 promise 不必要地使代码复杂化,只需使用 Promise.resolve
Promise.resolve(valueOrPromiseItDoesntMatter).then(function(value) {
})
回答by jib
Here's my original answer, which has since been ratified in the specas the way to test for a promise:
Promise.resolve(obj) == obj
This works because the algorithmexplicitly demands that Promise.resolvemust return the exact object passed in if and only ifit is a promise by the definition of the spec.
这是有效的,因为算法明确要求Promise.resolve必须返回传入的确切对象,当且仅当它是规范定义的承诺。
I have another answer here, which used to say this, but I changed it to something else when it didn't work with Safari at that time. That was a year ago, and this now works reliably even in Safari.
我在这里有另一个答案,它曾经说过这个,但是当它当时不适用于 Safari 时,我将其更改为其他内容。那是一年前,现在即使在 Safari 中也能可靠运行。
I would have edited my original answer, except that felt wrong, given that more people by now have voted for the altered solution in that answer than the original. I believe this is the better answer, and I hope you agree.
我会编辑我的原始答案,但感觉不对,因为现在投票支持该答案中更改的解决方案的人比原始答案多。我相信这是更好的答案,我希望你同意。
回答by jib
Update:This is no longer the best answer. Please vote up my other answerinstead.
更新:这不再是最佳答案。请投票给我的另一个答案。
obj instanceof Promise
should do it. Note that this may only work reliably with native es6 promises.
应该这样做。请注意,这可能仅适用于原生 es6 承诺。
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 .thenmethod), as shown in other answers here.
如果您使用 shim、promise 库或任何其他伪装成类似 promise 的东西,那么测试“thenable”(任何带有.then方法的东西)可能更合适,如此处的其他答案所示。
回答by unobf
if (typeof thing.then === 'function') {
// probably a promise
} else {
// definitely not a promise
}
回答by Boghyon Hoffmann
To see if the given object is a ES6 Promise, we can make use of this predicate:
要查看给定对象是否是ES6 Promise,我们可以使用以下谓词:
function isPromise(p) {
return p && Object.prototype.toString.call(p) === "[object Promise]";
}
Calling toStringdirectly from the Object.prototypereturns a native string representationof the given object type which is "[object Promise]"in our case. This ensures that the given object
Call荷兰国际集团toString直接从Object.prototype返回一个原生字符串表示,其是给定对象类型的"[object Promise]"在我们的例子。这确保给定的对象
- Bypasses false positives such as..:
- Self-defined object type with the same constructor name ("Promise").
- Self-written
toStringmethod of the given object.
- Works across multiple environment contexts (e.g. iframes) in contrast to
instanceoforisPrototypeOf.
- 绕过误报,例如..:
- 具有相同构造函数名称(“Promise”)的自定义对象类型。
toString给定对象的自写方法。
- 与
instanceof或相比,可以跨多个环境上下文(例如 iframe)工作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).
但是,任何通过 修改其标记的特定宿主对象都可以返回。这可能是预期的结果,也可能不是预期的结果,具体取决于项目(例如,如果有自定义的 Promise 实现)。Symbol.toStringTag"[object Promise]"
To see if the object is from a native ES6 Promise, we can use:
要查看对象是否来自原生 ES6 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
}
According to thisand this sectionof the spec, the string representation of function should be:
根据规范的this和this section,函数的字符串表示应该是:
"function Identifier( FormalParameterListopt) { FunctionBody}"
“函数标识符(FormalParameterList opt){ FunctionBody}”
which is handled accordingly above. The FunctionBodyis [native code]in all major browsers.
这是上面相应处理的。该函数体是[native code]在所有主流浏览器。
MDN: Function.prototype.toString
MDN: Function.prototype.toString
This works across multiple environment contexts as well.
这也适用于多个环境上下文。
回答by LEQADA
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 isPromisewas added which checks if an object is a native Promise or not:
不是完整问题的答案,但我认为值得一提的是,在 Node.js 10isPromise中添加了一个名为的新 util 函数,用于检查对象是否是本机 Promise:
const utilTypes = require('util').types
const b_Promise = require('bluebird')
utilTypes.isPromise(Promise.resolve(5)) // true
utilTypes.isPromise(b_Promise.resolve(5)) // false
回答by muratgozel
This is how graphql-jspackage detects promises:
这是graphql-js包检测承诺的方式:
function isPromise(value) {
return Boolean(value && typeof value.then === 'function');
}
valueis the returned value of your function. I'm using this code in my project and have no problem so far.
value是函数的返回值。我在我的项目中使用了这段代码,到目前为止没有问题。
回答by Steven Spungin
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.
如果函数返回promise,它将等待并返回解析值。如果函数返回一个值,它将被视为已解决。
If the function does not return a promise today, but tomorrow returns one or is declared async, you will be future-proof.
如果该函数今天没有返回承诺,但明天返回一个承诺或声明为异步,那么您将是面向未来的。
回答by Murilo Perrone
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, cis either a promise or one of my types which I want to convert into a promise by calling the c.fetch()method.
如果您使用的是Typescript,我想补充一点,您可以使用“类型谓词”功能。只需将逻辑验证包装在一个返回的函数中x is Promise<any>,您就不需要进行类型转换。下面在我的示例中,c是我想通过调用c.fetch()方法将其转换为承诺的承诺或我的类型之一。
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
更多信息:https: //www.typescriptlang.org/docs/handbook/advanced-types.html

