Ответ 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.Deferred
или Promise
1.
1. Если вы не работаете во враждебной среде, в этом случае вы, вероятно, должны отказаться.
Если вас не интересует jQuery promises, но вы хотите обнаружить любой тип Promise, включая встроенные из ECMAScript 6, вы можете проверить, является ли значение объектом и имеет метод then
if (typeof value === 'object' && typeof value.then === 'function') {
// handle a promise
} else {
// handle a concrete value
}
Это подход нескольких функций управления обещаниями, определенных в ES6. Вы можете увидеть это описание в спецификации функций resolve(...)
, частично цитируемое ниже:
Когда обещание разрешает функцию F вызывается с разрешением аргумента, выполняются следующие шаги:
[...]
- Если тип (разрешение) не является объектом, тогда
- Возврат FulfillPromise (обещание, разрешение).
- Пусть затем Get (разрешение,
"then"
).- Если это резкое завершение, то
- Возврат RejectPromise (обещание, затем. [[значение]]).
- Пусть thenAction будет тогда. [[value]].
- Если IsCallable (thenAction) false, тогда
- Возврат FulfillPromise (обещание, разрешение).
- Выполнить EnqueueJob (
"PromiseJobs"
, PromiseResolveThenableJob, "обещание, разрешение, затем действие" )