我如何判断一个对象是否是一个Promise?
无论是ES6承诺还是蓝鸟承诺,Q承诺等等。
我如何testing以查看给定对象是否是Promise?
承诺库如何决定
如果它有一个.then
函数 – 这是唯一的标准承诺库使用。
Promises / A +规范有一个叫做then
的概念,它基本上是“一个具有then
方法的对象”。 承诺将会并且应该用当时的方法来吸收任何东西 。 所有你提到的承诺实现都这样做。
如果我们看看规范 :
2.3.3.3如果
then
是一个函数,就用这个x来调用它,第一个参数是resolvePromise,第二个参数是rejectPromise
它也解释了这个devise决定的基本原理:
这样的处理可以允许promise实现互操作,只要它们公开Promise / A +的方法即可。 它还允许Promises / A +实现用合理的方法“吸收”不一致的实现。
你应该如何决定
你不应该 – 而是在Q中调用Promise.resolve(x)
( Q(x)
),它总是将任何值或外部值转换成可信任的承诺。 比自己执行这些检查更安全,更简单。
真的需要确定吗?
你总是可以通过testing套件运行它:D
检查某些东西是否是不必要的,使代码复杂化,只需使用Promise.resolve
Promise.resolve(valueOrPromiseItDoesntMatter).then(function(value) { })
这是我原来的答案, 在规范中被批准为testing承诺的方式:
Promise.resolve(obj) == obj
这是有效的,因为algorithm明确要求Promise.resolve
必须返回传入的确切对象,当且仅当它是由spec的定义的承诺。
我在这里有另外一个答案,这个答案曾经这样说过,但当时它不适用于Safari,我把它改成了别的东西。 那是一年前,即使在Safari上也可以正常工作。
我会编辑我原来的答案,只是觉得不对,因为现在有更多的人投票支持修改后的答案。 我相信这是更好的答案,我希望你同意。
更新:这不再是最好的答案。 请select我的其他答案 。
obj instanceof Promise
应该这样做。 请注意,这可能只能与本地es6承诺可靠地工作。
如果你正在使用垫片,承诺库或其他任何冒充类似promise的东西,那么testing一个“thenable”(任何带有.then方法的东西)可能更合适,如其他答案所示。
if (typeof thing.then === 'function') { // probably a promise } else { // definitely not a promise }
这里是代码formshttps://github.com/ssnau/xkit/blob/master/util/is-promise.js
!!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function';
如果一个对象有一个then
方法,那么应该把它当作一个Promise
。
it('should return a promise', function() { var result = testedFunctionThatReturnsPromise(); expect(result).toBeDefined(); // 3 slightly different ways of verifying a promise expect(typeof result.then).toBe('function'); expect(result instanceof Promise).toBe(true); expect(result).toBe(Promise.resolve(result)); });
要查看给定的对象是否是本地ES6 Promise ,我们可以使用这个谓词:
function isPromise (x) { return x && Object.prototype.toString.call(x) === "[object Promise]" }
直接从Object.prototype
调用toString
返回给定对象types的本地string表示 ,在我们的例子中是"[object Promise]"
。 这确保了给定的对象
- 绕过
- 具有相同构造函数名称(“Promise”)的自定义对象types。
- 自我重写
toString
方法给定的对象。
- 跨越多个环境上下文(例如iframe) 与
instanceof
。