延迟的jQuery AJAX包装器

时间:2013-02-06 08:49:30

标签: jquery ajax deferred

我正在为jQuery AJAX方法创建一个包装器,因为我的AJAX请求在实际进行之前依赖于异步工作。

我目前正在做的是: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

它有一个返回promise的外部延迟。我在实际执行AJAX请求之前解除了doAsyncWork()并等待它完成。现在,虽然这有效,但问题是当其他脚本使用包装器时,因为它们无法访问jQuery XHR对象的属性。

有没有办法优雅地解决这个问题?

2 个答案:

答案 0 :(得分:2)

问题是:他们为什么要这样做?您是否尝试使用包装器透明地替换$.ajax()?这将很快变得复杂,因为您必须考虑jqXHR的所有属性和方法。

从理论上讲,这样的事情是可能的,但我不会称之为优雅,不推荐

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

其他的readystate设置应该转到适当的回调(JQuery中没有onreadystatechange)。

那么,该怎么办?

如果其他脚本想要使用您的包装器,则必须使用Deferred API。如果由于某种原因他们确实需要访问jqXHR对象,您可以像这样提供:

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

用法:

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

答案 1 :(得分:0)

没有办法直接传递jqXHR对象,因为它不是在函数返回时创建的。

但是 - 不要忘记donefail回调中的jqXHR 分别可用作第三个和第一个参数。