JavaScript/jQuery 承诺链接
JavaScript/jQuery Promise chaining
尽管我无法(保密问题)分享太多信息,但我真的希望有人能帮助我解决这个问题。基本上,我写了这个函数来重试失败的承诺:
function retryOnFailure(func) {
return func().then(function(resp) {
return resp
}, function(err) {
return setTimeout(function() {
return retryOnFailure(func)
}, 5000)
}
)}
然后我有这段代码可以使用它:
function getStuff() {
return $.get('/some/endpoint')
}
retryOnFailure(getStuff).then(function(res) { console.log(res) })
现在递归重试功能可以正常工作,但是如果在 retryOnFailure
中出现错误情况,最后一行代码中的 then
不会触发。我知道原因是因为每次递归调用都会创建一个新的承诺,所以我在最后一行中听到的承诺与得到解决的承诺不同,但我很难弄清楚如何解决这个问题。我希望这个函数是一个通用的重试函数,因此不想处理方法中的实际成功,但我没有看到任何其他方式。任何帮助将不胜感激!
这是第一个想到的方法,可能还有更优雅的解决方案:
function retryOnFailure(func, onSuccess) {
return func().then(function(resp) {
onSuccess(resp);
}, function(err) {
return setTimeout(function() {
return retryOnFailure(func, onSuccess)
}, 5000)
}
)}
retryOnFailure(getStuff, function(res) { console.log(res) });
问题是您对 setTimeout
的调用,它打断了您的承诺流程。尝试这样的事情:
function retryOnFailure(func) {
return new Promise(function(resolve) {
func().then(function(resp) {
resolve(resp);
}).catch(function(err) {
setTimeout(function() {
retryOnFailure(func).then(resolve);
}, 5000)
});
});
};
retryOnFailure(getStuff).then(function(res) { console.log(res) });
请注意我是如何在函数中创建一个新的 promise 的,它从不抛出错误,而是简单地尝试处理 func()
并在失败时递归自身。
设置某种重试限制也是个好主意。
祝你好运!
return setTimeout(function() {
return retryOnFailure(func)
}, 5000)
看起来您正在尝试做正确的事情 - return
您的 .catch
回调的下一个结果。但是,setTimeout
没有 return 承诺,因此 retryOnFailure()
将立即解决(带有超时取消 ID)。
相反,您需要确保为您使用的所有异步函数生成一个承诺,所以让我们从承诺开始 setTimeout
:
function delay(ms) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, ms);
});
}
现在我们可以使用它在延迟后链接重试,并从中获得承诺:
function retryOnFailure(func) {
return func().then(null, function(err) {
return delay(5000).then(function() {
return retryOnFailure(func);
});
});
}
请注意,您还可以使用 .catch(…)
。
而不是 .then(null, …)
尽管我无法(保密问题)分享太多信息,但我真的希望有人能帮助我解决这个问题。基本上,我写了这个函数来重试失败的承诺:
function retryOnFailure(func) {
return func().then(function(resp) {
return resp
}, function(err) {
return setTimeout(function() {
return retryOnFailure(func)
}, 5000)
}
)}
然后我有这段代码可以使用它:
function getStuff() {
return $.get('/some/endpoint')
}
retryOnFailure(getStuff).then(function(res) { console.log(res) })
现在递归重试功能可以正常工作,但是如果在 retryOnFailure
中出现错误情况,最后一行代码中的 then
不会触发。我知道原因是因为每次递归调用都会创建一个新的承诺,所以我在最后一行中听到的承诺与得到解决的承诺不同,但我很难弄清楚如何解决这个问题。我希望这个函数是一个通用的重试函数,因此不想处理方法中的实际成功,但我没有看到任何其他方式。任何帮助将不胜感激!
这是第一个想到的方法,可能还有更优雅的解决方案:
function retryOnFailure(func, onSuccess) {
return func().then(function(resp) {
onSuccess(resp);
}, function(err) {
return setTimeout(function() {
return retryOnFailure(func, onSuccess)
}, 5000)
}
)}
retryOnFailure(getStuff, function(res) { console.log(res) });
问题是您对 setTimeout
的调用,它打断了您的承诺流程。尝试这样的事情:
function retryOnFailure(func) {
return new Promise(function(resolve) {
func().then(function(resp) {
resolve(resp);
}).catch(function(err) {
setTimeout(function() {
retryOnFailure(func).then(resolve);
}, 5000)
});
});
};
retryOnFailure(getStuff).then(function(res) { console.log(res) });
请注意我是如何在函数中创建一个新的 promise 的,它从不抛出错误,而是简单地尝试处理 func()
并在失败时递归自身。
设置某种重试限制也是个好主意。
祝你好运!
return setTimeout(function() { return retryOnFailure(func) }, 5000)
看起来您正在尝试做正确的事情 - return
您的 .catch
回调的下一个结果。但是,setTimeout
没有 return 承诺,因此 retryOnFailure()
将立即解决(带有超时取消 ID)。
相反,您需要确保为您使用的所有异步函数生成一个承诺,所以让我们从承诺开始 setTimeout
:
function delay(ms) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, ms);
});
}
现在我们可以使用它在延迟后链接重试,并从中获得承诺:
function retryOnFailure(func) {
return func().then(null, function(err) {
return delay(5000).then(function() {
return retryOnFailure(func);
});
});
}
请注意,您还可以使用 .catch(…)
。
.then(null, …)