3

我正在为 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

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

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

4

2 回答 2

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 设置应该去适当的回调(onreadystatechange在 JQuery 中没有)。

那么,该怎么做呢?

如果其他脚本想要使用您的包装器,它们将不得不使用 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;
});
于 2013-02-07T14:01:24.030 回答
0

无法直接传递 jqXHR 对象,因为它在函数返回时尚未创建。

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

于 2013-02-07T14:53:12.787 回答