我正在尝试实现一个重试由于临时原因失败的 ajax 请求的系统。在我的情况下,它是关于在调用恢复会话的刷新 Web 服务之后重试由于会话已过期而失败并显示 401 状态代码的请求。
问题是在成功重试时不会调用“完成”回调,这与调用的“成功”ajax 选项回调不同。我在下面做了一个简单的例子:
$.ajaxSetup({statusCode: {
404: function() {
this.url = '/existent_url';
$.ajax(this);
}
}});
$.ajax({
url: '/inexistent_url',
success: function() { alert('success'); }
})
.done(function() {
alert('done');
});
有没有办法在成功重试时调用完成式回调?我知道延迟被“拒绝”后无法“解决”,是否可以防止拒绝?或者也许将原始 deferred 的 doneList 复制到新的 deferred?我没有想法:)
下面是一个更现实的例子,我试图将所有 401 拒绝的请求排队,并在成功调用 /refresh 后重试它们。
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 失败的请求被第二次触发,问题是它们的“完成”回调没有被调用,因此应用程序停止。