我需要创建一个重试失败的ajax请求的函数,直到给定的限制,但是我需要确保只有在超过最大重试次数时拒绝承诺,如下所示:
function my_ajax(...) { ... }
// then I use it this way
return $.when(my_ajax('foo.json'), my_ajax('bar.json'))
为了使用jQuery.when,只应返回my_ajax
的一个promise,这应该在解析内部jQuery.ajax时解析,并且只在最大重试次数时才被拒绝。 / p>
我制作的代码是:
function do_ajax(args, dfd, attempt) {
dfd || (dfd = $.Deferred());
attempt || (attempt = 1);
$.ajax(args).then(dfd.resolve, function(xhr, text_status, error_thrown) {
console.error(/* something useful */);
attempt++;
if(attempt > 3) {
dfd.reject(xhr, text_status, error_thrown);
} else {
do_ajax(args, dfd, attempt);
}
});
return dfd.promise();
}
// in some random code
return $.when(do_ajax({url:'foo.json'}), do_ajax({url:'bar.json'});
这对我有用*,但有点难以理解。问题是:有没有更好(更容易阅读)的方法呢?
* - 实际上我有时候没有测试失败,但是当第一个ajax请求成功时我工作正常。
答案 0 :(得分:3)
我认为您的代码是正确的方法,将您的调用包装在新的Deferred中并返回,直到达到所有尝试。
您可以尝试在匿名函数中包含递归调用,以提高可读性。
我是这样写的:function doAjax(ajaxArgs, attempt) {
// the wrapped returned dfd
var wrappedDfd = $.Deferred();
// your nested call using attempt counter
(function nestedCall() {
// if call succed, resolve the wrapped dfd
$.ajax(ajaxArgs).then(wrappedDfd.resolve, function() {
// update attempt counter
attempt--;
if (attempt > 0) {
// try another call
nestedCall();
} else {
// max try reached, reject wrapped dfd
wrappedDfd.reject();
}
});
})();
return wrappedDfd.promise();
};
这与您的代码非常相似。
这是jsfiddle。出于测试目的,我通过模拟工厂调用替换了doAjax参数,但代码保持不变。
希望得到这个帮助。
答案 1 :(得分:1)
根据Mordhak的答案和SO dherman周围的其他几个人创建了一个jQuery插件:jquery.ajaxRetry(GitHub repo),johnkpaul 也是如此:jquery.ajax-retry
<强> jquery.ajaxRetry 强>
实施例
$.ajax({
// Retry this request up to 2 times
shouldRetry: 2
});
n
次true
中的false
或shouldRetry
以确定是否应继续重试<强> jquery.ajax重试强>
实施例
$.ajax(options).retry({times:3, timeout:3000}).then(function(){
alert("success!");
});
n
次