我有一个带有单个参数的函数。我需要能够判断这个参数是jQuery Promise
还是Deferred
对象。如果没有,那么该值可以是任何类型并且具有任何属性,因此仅仅存在promise方法是不安全的。
以下是我希望我的功能如何运作的示例:
function displayMessage(message) {
if (message is a Promise or Deferred) {
message.then(displayMessage);
} else {
alert(message);
}
}
注意promises的递归处理:如果使用另一个promise值解析promise而我们不显示它,我们等待它被解析。如果它又返回另一个承诺,请重复。
这很重要,因为如果不是这样,我就可以使用jQuery.when
:
function displayMessage(message) {
jQuery.when(message).then(function(messageString) {
alert(messageString);
});
}
这将正确处理值的值和承诺...
displayMessage("hello"); // alerts "hello"
displayMessage(jQuery.Deferred().resolve("hello")); // alerts "hello"
......但是一旦我们接受了价值承诺的承诺,就会崩溃:
displayMessage(jQuery.Deferred().resolve(
jQuery.Deferred().resolve("hello")
)); // alerts "[object Object]"
jQuery.when
能够判断一个值是否是承诺,所以显然它是可能的。我怎么检查?
答案 0 :(得分:32)
jQuery.when
能够判断一个值是否是承诺,所以显然它是可能的。
这是错误的。 jQuery本身无法检查对象是否是完全准确的承诺。如果您查看jQuery.when
in the jQuery source viewer的来源,您可以看到它所做的就是:
jQuery.isFunction(firstParam.promise)
如果您要返回的对象有自己的.promise()
方法,jQuery.when
会出错:
var trickyValue = {
promise: function() { return 3; },
value: 2
};
jQuery.when(trickyValue).then(function(obj) {
alert(obj.value);
});
抛出TypeError: Object 3 has no method 'then'
,因为jQuery假定对象是一个promise并且信任其.promise()
方法的值。
这可能无法正确解决。 promise对象在jQuery.Deferred
(view source)内创建为对象文字。它没有原型,也没有任何其他真正独特的属性可以用来区分它。
但是,只要只使用一个版本的jQuery,我就能想到一个应该可靠的hacky解决方案:
function isPromise(value) {
if (typeof value === 'object' && typeof value.then !== "function") {
return false;
}
var promiseThenSrc = String($.Deferred().then);
var valueThenSrc = String(value.then);
return promiseThenSrc === valueThenSrc;
}
isPromise("test"); // false
isPromise($.Deferred()); // true
isPromise($.Deferred().promise()); // true
将函数转换为字符串会为您提供源代码,因此我在这里将新.then
对象的Deferred
方法的源与我感兴趣的值进行比较。您的值不会是.then
方法,其源代码与jQuery.Deferred
或Promise
1 完全相同。
1。除非你在恶劣的环境中运行,否则你应该放弃。
如果你对jQuery promises没有特别的兴趣,但是想要检测任何类型的Promise,包括来自ECMAScript 6的内置类型,你可以测试value是否是一个对象并且有一个then
方法:
if (typeof value === 'object' && typeof value.then === 'function') {
// handle a promise
} else {
// handle a concrete value
}
这是ES6中定义的几个Promise处理函数的方法。您可以看到in the specification of the resolve(...)
functions描述的内容,部分引用如下:
当使用参数 resolution 调用promise resolve函数 F 时,将执行以下步骤:
[...]
- 如果Type( resolution )不是Object,那么
- 返回FulfillPromise(承诺,解决方案)。
- 然后让我们获取(解决方案,
"then"
)。- 如果那时突然完成,那么
- 返回RejectPromise(承诺,然后。[[value]])。
- 让 thenAction 为然后。[[value]]。
- 如果IsCallable( thenAction ) false ,则
- 返回FulfillPromise(承诺,解决方案)。
- 执行EnqueueJob(
醇>"PromiseJobs"
,PromiseResolveThenableJob,«promise,resolution,thenAction»)
答案 1 :(得分:14)
快速而肮脏的解决方案是测试对象是否具有then
函数:
if (typeof message.then === 'function') {
//assume it's a Deferred or fits the Deferred interface
} else {
//do other stuff
}