JQuery jqXHR - отменить прикованные вызовы, цепочку ошибок запуска

Я создаю утилиту ajax для взаимодействия с моими методами сервера. Я хотел бы использовать jQuery 1.5+ отложенные методы из объекта, возвращенного из вызова jQuery.ajax(). Ситуация следующая.

  • Метод serveride всегда возвращает объект 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

( UPDATE: Обратите внимание, что в настоящее время jQuery Promises несовместим с 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() оставлена ​​в качестве упражнения для читателя.)

Смотрите эти демонстрации:

Вот еще один пример, взятый непосредственно из рабочего проекта:

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;
}