jQuery jqXHR – cancel chained calls, trigger error chain

(UPDATE:
Please note that currently jQuery Promises are not compatible with the Promises/A+ specification – more info in this answer.)

In your function where you create the AJAX request you can also create a deferred object and return a promise to the caller after binding its resolve and reject functions to the appropriate callbacks of the $.ajax request with some custom data verification, like this:

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

Now anyone will be able to use it like any promise like this to your function:

var request = makerequest();

request.done(successCallback);
request.fail(errorCallback);

Or even just:

makerequest().then(successCallback, errorCallback);

If you also add this:

    promise.success = promise.done;
    promise.error = promise.fail;

then your caller will have (maybe more familiar) interface of .success() and .error() like with pure $.ajax() calls:

var request = makerequest();

request.success(successCallback);
request.error(errorCallback);

(The implementation of .complete() is left as an exercise for the reader.)

See this demos:

Here’s another example pulled directly from a working project:

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

Leave a Comment