jQuery jqXHR - отмена связанных вызовов, запуск цепочки ошибок - PullRequest
14 голосов
/ 25 февраля 2011

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

  1. Метод сервера всегда возвращает объект JSON:

    { success: true|false, data: ... }

  2. Утилита на стороне клиента инициирует вызов ajax следующим образом

    var jqxhr = $.ajax({ ... });

  3. И проблемная зона:

    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 Ответ

29 голосов
/ 25 февраля 2011

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

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

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

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