jQuery jqXHR - отмена связанных вызовов, запуск цепочки ошибок

Я создаю 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 ответ

Решение

(ОБНОВЛЕНИЕ: обратите внимание, что в настоящее время обещания 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;
}
Другие вопросы по тегам