无论是ES6承诺还是蓝鸟承诺,Q承诺等等。

我如何测试,看看一个给定的对象是一个承诺?


当前回答

免责声明:对更新OP不是一个很好的答案,只适用于本机,不能跨领域。而是遵循公认的答案。

obj instanceof Promise

应该这么做。请注意,这可能只与本地es6承诺可靠地工作。

如果您正在使用一个shim、一个promise库或任何假装类似promise的东西,那么可能更适合测试“thenable”(任何带有.then方法的东西),如这里的其他答案所示。

其他回答

在寻找一个可靠的方法来检测Async函数甚至承诺后,我最终使用了以下测试:

() => fn.constructor.name === 'Promise' || fn.constructor.name === 'AsyncFunction'

要查看给定对象是否为ES6 Promise,可以使用以下谓词:

function isPromise(p) {
  return p && Object.prototype.toString.call(p) === "[object Promise]";
}

直接从对象调用toString。prototype返回给定对象类型的原生字符串表示,在本例中为“[object Promise]”。这确保了给定的对象

绕过误报,如..: 具有相同构造函数名称(“Promise”)的自定义对象类型。 给定对象的自写toString方法。 与instanceof或isPrototypeOf相比,可以跨多个环境上下文(例如iframes)工作。

然而,任何特定的宿主对象,其标记通过Symbol被修改。toStringTag,可以返回“[object Promise]”。这可能是预期的结果,也可能不是,这取决于项目(例如,如果有一个自定义的承诺实现)。


要查看该对象是否来自本地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 
}

根据本节和规范的这一部分,函数的字符串表示形式应该是:

函数标识符(FormalParameterListopt) {FunctionBody}"

这是上面相应的处理。在所有主流浏览器中,FunctionBody都是[本机代码]。

MDN: Function.prototype.toString

这也适用于多个环境上下文。

使用这个库

https://www.npmjs.com/package/is-promise

import isPromise from 'is-promise';
 
isPromise(Promise.resolve());//=>true
isPromise({then:function () {...}});//=>true
isPromise(null);//=>false
isPromise({});//=>false
isPromise({then: true})//=>false

这是graphql-js包检测承诺的方式:

function isPromise(value) {
  return Boolean(value && typeof value.then === 'function');
}

Value是函数的返回值。我在我的项目中使用这段代码,到目前为止还没有问题。

const isPromise = (value) => {
  return !!(
    value &&
    value.then &&
    typeof value.then === 'function' &&
    value?.constructor?.name === 'Promise'
  )
}

对我来说,这张支票更好,试试吧