#jquery #typescript #promise
#jquery #typescript #обещание
Вопрос:
Я ищу лучший способ исправить эту ситуацию. Мне нужны дополнительные проверки возвращенных данных Ajax, которые могут привести _loadPanel
к сбою моей операции обещания:
_loadPanel(url: string, data?: any) : JQueryPromise<any>
{
return $.ajax(
{
url: url,
type: data ? "POST" : "GET",
data: data
}).done(function (html: string, textStatus: string)
{
// Some function that exracts required data
var $panel = extractPanelData(html);
if (!$panel.length)
{
// How to cause a reject here???
}
});
}
Вы не можете этого сделать (ниже), поскольку обещание, возвращаемое из Ajax, является неизменяемым, и оно все равно пахнет неправильно:
var promise = $.ajax({...}).done(function(...)
{
promise.reject("Data failed promise");
});
Есть ли простой способ сделать это, который не требует добавления дополнительного $.Deferred()
объекта или это единственный шаблон?
Попытки:
Я попробовал следующее, чтобы я мог изменить родительский Deferred
объект, но он не будет компилироваться:
var dfd = $.Deferred();
var promise = dfd.promise();
promise = promise.then($.ajax(
{
cache: false,
url: url,
type: data ? "POST" : "GET",
data: data
}).done(...));
Это позволит мне объединить Ajax
обещание с Deferred
обещанием
Supplied parameters do not match any signature of call target:Type '(value: {}) => {}' requires a call signature, but type 'JQueryXHR' lacks one.
Предложения?
Что-то классное:
Не уверен, насколько это широко известно, и это не помогает этой проблеме (поскольку оно также возвращает неизменяемое обещание), но, похоже, вы можете использовать $.when
для передачи начальных параметров первой функции
например, передача начальных параметров $.ajax
таким образом:
$.when({
url: url,
type: data? "POST" : "GET",
data: data
}).then($.ajax).done(function (html: string, textStatus: string)
или отдельные параметры, подобные этому:
$.when("Hello!", 22, "There!")
.then(insertPanel);
Это может иметь интересные преимущества, если результат привязан к предыдущим обещаниям, поскольку вызов Ajax больше не выполняется немедленно, а только после завершения предыдущих шагов.
Комментарии:
1. если вы хотите отклонить,
throw
изthen
.2. @Daniel A. White: Вы подразумеваете, что система исключений привязана к системе обещаний jQuery?
3. обещания jquery должны обрабатывать исключения
4. @Daniel A. White: У вас есть ссылка, поскольку я не нахожу ничего полезного (пока). Я не знал, что они обрабатывают исключения в асинхронных операциях.
5. вы могли бы использовать Q и обернуть им обещание jquery.
Ответ №1:
Здесь есть несколько особенностей:
.then
связывает обещания и изменяет их состояние..done
не связывает обещания, а добавляет обработчик к текущему обещанию и возвращает его.
Итак:
var xhr = $.ajax({...});
p = xhr.then(function(data){
// fail if check fails
if(additionalChecksFail) return $.Deferred.reject(Error("Invalid Request").promise();
return data; // otherwise we maintain the same data
});
p.then(function(data){
// will only run if data validation passed.
});
Комментарии:
1. Я, хотя
done
и вернул исходное обещание, поскольку они действительно связаны (обычно сfail
next).2. @TrueBlueAussie да, он возвращает исходное обещание, он не связывает обещания (подумайте о реальной цепочке для этой аналогии :)).
3. Тогда я не понимаю, почему я не мог этого сделать
.then($ajax().done())
, что и делала моя попытка (если вы игнорируете детали). Это должен быть тот же объект,.then($ajax())
который я считал действительным. Это просто сильная проблема с типизацией в Typescript?4. @TrueBlueAussie
$ajax
возвращает обещание, в котором.then
принимает функцию, которую вы можете сделать.then(function(res){ return $.ajax(..); })
, это похоже на то, как вы передаете функцию обратного вызова вместо ее прямого вызова.5. Я использовал
then
для цепочки функций, которые возвращают обещания в тестах. jsfiddle.net/TrueBlueAussie/s8XmJ/1 Он выполняет обещания последовательно, связывает результаты для последующихthen