我有一个函数,它接受一个参数。 我需要能够告诉如果这种说法是一个jQuery Promise
或Deferred
对象。 如果没有,则该值可以是任何类型和任何属性,所以它不是安全的,才刚刚进行的承诺方式存在。
下面是我想如何我的功能表现为例:
function displayMessage(message) {
if (message is a Promise or Deferred) {
message.then(displayMessage);
} else {
alert(message);
}
}
注意承诺的递归处理:如果一个承诺与另一个承诺值,我们不显示它解决,我们等待它来解决。 如果返回另一个承诺,重复。
因为如果不是这种情况,我只是将能够利用这一点很重要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
能够判断一个值是承诺,所以显然这是可能的。 我该如何检查?
jQuery.when
能够判断一个值是承诺,所以显然这是可能的。
这是错误的。 jQuery的本身是不是能检查对象是否完全准确的承诺。 如果你看一下源jQuery.when
在jQuery的源代码查看器 ,你可以看到,它所做的是这样的:
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()
方法。
这大概是不可能的妥善解决。 许对象作为对象的内部字面创建jQuery.Deferred
( 视图源 )。 它有没有原型,也可用于其他任何真正独特的特性来区分它。
不过,我能想到的一个哈克的解决方案,应该是可靠的,只要只有一个版本的jQuery的是在使用的:
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的承诺特别感兴趣,但想从ECMAScript中6检测到任何类型的承诺,包括内置的,你可以测试是否值是一个对象,具有then
方法:
if (typeof value === 'object' && typeof value.then === 'function') {
// handle a promise
} else {
// handle a concrete value
}
这是在ES6定义的一些承诺处理函数的方法。 你可以看到这个描述中的规格resolve(...)
功能 ,部分报价如下:
当一个承诺解决函数F调用参数的分辨率 ,采取以下步骤:
[...]
- 如果Type( 分辨率 )不是Object,则
- 返回FulfillPromise( 承诺 , 分辨率 )。
- 那么,让被获取( 分辨率 ,
"then"
)。 - 如果然后是突然完成,然后
- 返回RejectPromise( 承诺 , 则 [[值]])。
- 让thenAction是那么 [[价值]。
- 如果IsCallable(thenAction)是假的 ,那么
- 返回FulfillPromise( 承诺 , 分辨率 )。
- 执行EnqueueJob(
"PromiseJobs"
,PromiseResolveThenableJob,«承诺,分辨率thenAction»)
快速和肮脏的解决方案是测试,如果对象具有then
函数:
if (typeof message.then === 'function') {
//assume it's a Deferred or fits the Deferred interface
} else {
//do other stuff
}