我正在尝试解决一个非常简单的问题,但我无法弄清楚。 我有以下代码:
<button onclick="run()">TEST</button>
<script>
var counter = 0;
function test() {
return $.ajax({
url: "https://127.0.0.1:4432",
success: function(html){
console.log('success! test');
},
error: function() {
if (counter++ < 3) {
console.log("Retrying");
$.ajax(this);
return;
}
console.log('ERROR! test');
}
});
}
function run() {
test()
.then(
function(){console.log('finished ALL OK')},
function() {console.log('finished all ERROR')
;});
}
</script>
我要实现的是,单击按钮后,AJAX请求将发送到服务器。如果AJAX失败,则将重试该请求。只有在所有重试完成后,才会调用“ .then”功能的成功或失败。
此刻,代码的行为就像AJAX调用被重试了三次一样,但是在第一次失败之后立即调用“ .then()”处理程序。
在浏览器的控制台中,它看起来像这样:
所有重试后,我希望在最后看到“完成所有错误”文字。
希望这是有道理的,我将不胜感激。
答案 0 :(得分:1)
success
方法中的任何内容都不会影响同一jqXHR对象上的.then
。对于您要寻找的链接,请考虑使用 .then
和.catch
es代替:
function test() {
let counter = 0;
const get = () => $.ajax({ url: "https://127.0.0.1:4432" })
.then((html) => {
console.log('success');
})
.catch((err) => {
if (counter++ < 3) {
console.log("Retrying");
return get();
}
console.log('ERROR! test');
throw new Error();
});
return get();
}
test()
.then(
function() {
console.log('finished ALL OK')
},
function() {
console.log('finished all ERROR');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
答案 1 :(得分:0)
function test(counter, $existingDeferred) {
var $deferred = $existingDeferred || $.Deferred();
$.ajax({
url: "https://127.0.0.1:4432",
success: function(html){
console.log('success! test');
$deferred.resolve(arguments);
},
error: function() {
console.log('ERROR! test');
if (counter < 3) {
console.log("Retrying");
test(++counter, $deferred);
} else {
$deferred.reject(arguments);
}
}
});
return $deferred;
}
function run() {
test(0)
.then(
function(){console.log('finished ALL OK')},
function() {console.log('finished all ERROR')
;});
}
您可以设置辅助延迟,以控制重试尝试的时间。
答案 2 :(得分:0)
这是使用递归的另一种选择。
function test(fn, retries) {
return fn().catch(error =>
retries > 0 ? test(fn, retries - 1) : Promise.reject(error)
);
}
test(() => $.ajax({ url: "https://127.0.0.1:4432" }), 3)
.then(data => console.log('finished ALL OK'))
.catch(lastError => console.log('finished all ERROR'));
如果以成功的响应调用了fn
,则永远不会调用catch
来停止递归。如果fn
没有得到肯定的答复,它将检查是否还有重试。如果是这种情况,它将以较少的重试次数再次调用test
,如果没有重试,则调用Promise.reject
,以提供最后的错误。
注意:如果您未使用jQuery 3.0或更高版本,则必须将.catch(...)
替换为.then(null, ...)
。
答案 3 :(得分:-1)
一种可能的解决方案是将整个操作包装在Promise中,尽管您可能需要使用polyfill来获得100%的浏览器支持。看起来像这样:
function test() {
return new Promise(function(resolve, reject) {
var counter = 0;
$.ajax({
url: "https://127.0.0.1:4432",
success: function(html){
console.log('success! test');
resolve(html);
},
error: function() {
if (counter++ < 3) {
console.log("Retrying");
$.ajax(this);
}
console.log('ERROR! test');
reject('retries exceeded');
}
});
});
}
function run() {
test().then(
function() { console.log('finished ALL OK'); },
function() { console.log('finished all ERROR'); }
);
}