【问题标题】:How to retry fetch in a loop when it throws an error抛出错误时如何在循环中重试获取
【发布时间】:2020-06-03 00:06:46
【问题描述】:
我有以下JS函数:
func() {
return fetch({
...
}).then({
...
})catch({
...
})
}
在其中我返回一个由fetch() 返回的承诺。如果它失败(即调用catch() 块)我想重复整个事情。就像将整个事情放在 while (true) 循环中一样,但我不知道如何使用 Promise 来做到这一点。
有什么建议吗?
【问题讨论】:
标签:
promise
try-catch
fetch
es6-promise
【解决方案1】:
您可以简单地编写一个循环并计算尝试次数,直到一次成功或您用完为止。 async/await 让这一切变得简单。请参阅下面的一个最小的完整示例。
请注意,获取 API 使用 response.ok 标志来确保响应状态落在 200 范围内。用try/catch 包装仅足以覆盖连接失败。如果响应指示错误请求,则重试可能不合适。此代码在这种情况下解决了承诺,但您可以将 !response.ok 视为错误并根据需要重试。
const fetchWithRetry = async (url, opts, tries=2) => {
const errs = [];
for (let i = 0; i < tries; i++) {
// log for illustration
console.log(`trying GET '${url}' [${i + 1} of ${tries}]`);
try {
return await fetch(url, opts);
}
catch (err) {
errs.push(err);
}
}
throw errs;
};
fetchWithRetry("https://httpstat.us/400")
.then(response => console.log("response is OK? " + response.ok))
.catch(err => console.error(err));
fetchWithRetry("foo")
.catch(err => console.error(err.map(e => e.toString())));
fetchWithRetry("https://httpstat.us/200")
.then(response => response.text())
.then(data => console.log(data))
.catch(err => console.error(err));
如果您想要无限次重试,请将 tries 参数传递为 -1(但这对我来说似乎并不常见)。
【解决方案2】:
你应该仔细看看 promises 和 async await。
async function fetchUntilSucceeded() {
let success = false;
while(!success) {
try {
let result = await fetch(...);
success = true;
//do your stuff with your result here
} catch {
//do your catch stuff here
}
}
}
如果你只需要结果:
async function fetchUntilSucceeded() {
while(true) {
try {
return await fetch(...);
}
}
}
但是要小心这样的代码,因为它可能永远无法解析!它还可以发送大量请求而无需任何等待时间。