我试图实现一个系统重试ajax请求失败的临时原因。在我的情况下,它是关于重试请求失败的401状态代码,因为会话已过期,在调用刷新webservice恢复会话后。
问题是,“done”回调不会在成功的重试上调用,与调用的“success”ajax选项回调不同。我已经做了一个简单的例子如下:
@H_403_4@$.ajaxSetup({statusCode: { 404: function() { this.url = '/existent_url'; $.ajax(this); } }}); $.ajax({ url: '/inexistent_url',success: function() { alert('success'); } }) .done(function() { alert('done'); });有没有一种方法来完成样式的回调调用成功的重试?我知道一个推迟的人在“被拒绝”之后不能被“解决”,是否有可能防止被拒绝?或者也许复制原始延迟的doneList到新的延迟?我的想法:)
一个更现实的示例如下,其中我试图排队所有401拒绝的请求,并在成功调用/刷新后重试它们。
@H_403_4@var refreshRequest = null,waitingRequests = null; var expiredTokenHandler = function(xhr,textStatus,errorThrown) { //only the first rejected request will fire up the /refresh call if(!refreshRequest) { waitingRequests = $.Deferred(); refreshRequest = $.ajax({ url: '/refresh',success: function(data) { // session refreshed,good refreshRequest = null; waitingRequests.resolve(); },error: function(data) { // session can't be saved waitingRequests.reject(); alert('Your session has expired. Sorry.'); } }); } // put the current request into the waiting queue (function(request) { waitingRequests.done(function() { // retry the request $.ajax(request); }); })(this); } $.ajaxSetup({statusCode: { 401: expiredTokenHandler }});机制工作,401失败的请求第二次被触发,问题是他们的“完成”回调没有被调用,所以应用程序停顿。
解决方法
你可以使用
jQuery.ajaxPrefilter
将jqXHR包装在另一个
deferred object。
我做了一个例子,jsFiddle
显示它的工作,并试图适应一些你的代码来处理401到这个版本:
这是因为deferred.promise(object)
实际上会覆盖jqXHR上的所有“promise方法”。
注意:任何人发现这一点,如果你附加回调成功:和错误:在ajax选项,这个片段将无法按预期的方式工作。它假定唯一的回调是使用jqXHR的.done(callback)和.fail(callback)方法附加的回调。