Deferred jQuery AJAX wrapper

I am wrapping a jQuery AJAX method because my AJAX requests depend on working asynchronously before actually continuing.

What I'm currently doing is: http://pastie.org/private/bfdvep4kcdclzupsyddmiq

var ajax = function (options) {
    var deferred = $.Deferred();

    doAsyncWork()
    .done(function (attributes) {
        $.ajax(options)
        .done(function () {
            deferred.resolve.apply(this, arguments);
        })
        .fail(function () {
            deferred.reject.apply(this, arguments);
        });
    })
    .fail(function () {
        deferred.reject();
    });

    return deferred.promise();
};

ajax().readyState // undefined

      

It has an outer deferred that returns a promise. I run doAsyncWork () and wait for it to complete before making an AJAX request. Now that this works, the problem is when other scripts are using the wrapper because they cannot access the properties of the jQuery XHR object.

Is there a way to solve this problem?

+3


source to share


2 answers


The question is: why do they need it? Are you trying to replace $.ajax()

transparently with your wrapper? This will quickly get complicated as you will need to consider all the properties and methods jqXHR

.

In theory something like this is possible, but I would not call it elegant and would not recommend it:

var ajax = function (options) {
    var deferred = $.Deferred();
    var promise = deferred.promise();

    doAsyncWork()
    .done(function (attributes) {
        $.ajax(options)
        .done(function () {
            promise.readyState = 4
            deferred.resolve.apply(this, arguments);
        })
        .fail(function () {
            promise.readyState = 4
            deferred.reject.apply(this, arguments);
        });
    })
    .fail(function () {
        deferred.reject();
    });

    promise.readyState = 0;
    return promise;
};

      

The other readistate parameters should go to their respective callbacks (not in JQuery onreadystatechange

).

So what do you do instead?



If other scripts want to use your wrapper, they will have to use the deferred API. If for some reason they really need to access the object jqXHR

, you can provide it like this:

var ajax = function (options, xhrReadyCallback) {
    var deferred = $.Deferred();

    doAsyncWork()
    .done(function (attributes) {
        var xhr = $.ajax(options)
        .done(function () {
            deferred.resolve.apply(this, arguments);
        })
        .fail(function () {
            deferred.reject.apply(this, arguments);
        });
        xhrReadyCallback(xhr);
    })
    .fail(function () {
        deferred.reject();
    });

    return deferred.promise();
};

      

Using:

ajax(options, function(xhr) {
    // now available:
    xhr.readyState;
});

      

+2


source


It is not possible to pass the jqXHR object directly, because it is not created by the time the function returns.



But - do not forget that jqXHR available in callbacks done

and fail

, and in the third and the first parameter, respectively.

0


source







All Articles