我如何判断一个对象是一个jQuery无极/递延?(How can I tell if an obje

2019-08-01 23:06发布

我有一个函数,它接受一个参数。 我需要能够告诉如果这种说法是一个jQuery PromiseDeferred对象。 如果没有,则该值可以是任何类型和任何属性,所以它不是安全的,才刚刚进行的承诺方式存在。

下面是我想如何我的功能表现为例:

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能够判断一个值是承诺,所以显然这是可能的。 我该如何检查?

Answer 1:

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.DeferredPromise 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调用参数的分辨率 ,采取以下步骤:

[...]

  1. 如果Type( 分辨率 )不是Object,则
    1. 返回FulfillPromise( 承诺分辨率 )。
  2. 那么,让被获取( 分辨率"then" )。
  3. 如果然后是突然完成,然后
    1. 返回RejectPromise( 承诺 [[值]])。
  4. thenAction那么 [[价值]。
  5. 如果IsCallable(thenAction)假的 ,那么
    1. 返回FulfillPromise( 承诺分辨率 )。
  6. 执行EnqueueJob( "PromiseJobs" ,PromiseResolveThenableJob,«承诺,分辨率thenAction»)


Answer 2:

快速和肮脏的解决方案是测试,如果对象具有then函数:

if (typeof message.then === 'function') {
    //assume it's a Deferred or fits the Deferred interface
} else {
    //do other stuff
}


文章来源: How can I tell if an object is a jQuery Promise/Deferred?