jQuery jqXHR - отмена связанных вызовов, запуск цепочки ошибок
Я создаю ajax-утилиту для взаимодействия с методами моего сервера. Я хотел бы использовать отложенные методы jQuery 1.5+ из объекта, возвращаемого из вызова jQuery.ajax(). Ситуация следующая.
Серверный метод всегда возвращает объект JSON:
{ success: true|false, data: ... }
Утилита на стороне клиента инициирует вызов ajax следующим образом
var jqxhr = $.ajax({ ... });
И проблемная зона:
jqxhr.success(function(data, textStatus, xhr) { if(!data || !data.success) { ???? // abort processing, trigger error } }); return jqxhr; // return to caller so he can attach his own handlers
Таким образом, вопрос заключается в том, как отменить вызов всех вызовов, добавленных при успешном вызове, и вызвать его обработчик ошибок в месте, указанном ????
?
В документации говорится, что списки вызовов отложенных функций являются FIFO, поэтому мой обработчик успеха определенно является первым.
1 ответ
(ОБНОВЛЕНИЕ: обратите внимание, что в настоящее время обещания jQuery не совместимы со спецификацией Promises/A+ - больше информации в этом ответе.)
В вашей функции, где вы создаете запрос AJAX, вы также можете создать отложенный объект и вернуть обещание вызывающей стороне после привязки его функций разрешения и отклонения к соответствующим обратным вызовам запроса $.ajax с некоторой проверкой пользовательских данных, например:
function makerequest() {
var deferred = $.Deferred();
var promise = deferred.promise();
var jqxhr = $.ajax({
// ...
});
jqxhr.success(function(data, status, xhr) {
if (!data || !data.success) {
deferred.reject(jqxhr, 'error');
} else {
deferred.resolve(data, status, xhr);
}
});
jqxhr.error(function(jqXHR, status, error) {
deferred.reject(jqXHR, status, error);
});
return promise;
}
Теперь любой сможет использовать его, как любое обещание, подобное вашей функции:
var request = makerequest();
request.done(successCallback);
request.fail(errorCallback);
Или даже просто:
makerequest().then(successCallback, errorCallback);
Если вы также добавите это:
promise.success = promise.done;
promise.error = promise.fail;
тогда у вашего абонента будет (возможно, более знакомый) интерфейс.success() и.error(), как с чистыми вызовами $.ajax():
var request = makerequest();
request.success(successCallback);
request.error(errorCallback);
(Реализация.complete() оставлена в качестве упражнения для читателя.)
Смотрите это демо:
- http://jsfiddle.net/_rsp/r2YnM/
- http://jsfiddle.net/_rsp/r2YnM/1/ (более подробный)
Вот еще один пример, взятый непосредственно из рабочего проекта:
function ajax(url, data) {
var self = this;
var deferred = $.Deferred();
var promise = deferred.promise();
var jqxhr = $.ajax({
url: url,
data: JSON.stringify(data),
contentType: "application/json; charset=utf-8",
dataType: 'json',
type: 'POST'
}).done(function (msg, status, xhr) {
if (!msg || msg.Error) {
self.doError(msg.Error);
deferred.reject(jqxhr, 'error');
} else {
deferred.resolve(msg, status, xhr);
}
});
return promise;
}