2013-02-06 42 views
3

我正在为jQuery AJAX方法创建一个包装器,因为在实际进行之前,我的AJAX请求依赖于异步工作。推迟的jQuery 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对象的属性。

有没有办法解决这个优雅?

+0

传递'function(){deferred.resolve.apply(this,arguments);}'就像传递'deferred.resolve'一样,但后者不需要额外的闭包。 – Alnitak

回答

2

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

从理论上讲,这样的事情是可能的,但我不会把它优雅不建议它:

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的)。

那么,该怎么做呢?

如果其他脚本想要使用你的包装,他们将不得不使用延迟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; 
}); 
+0

这是一个很好的解决方案!非常感谢。 – Morten

0

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

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