如何判断捕获到的fetch错误是否可重试?
我想弄清楚如何判断捕获到的 fetch 错误是否可重试。
try
{
let response = fetch(url);
}
catch(error)
{
...
}
我知道 fetch 在服务器响应错误时不会失败(例如404)
不过,从我看到的情况来看,错误可能被抛出/捕获的一些原因有以下几种:
- DNS/网络问题 - 可重试
- 无效的URL方案(如
xhttps://www.google.com)- 不可重试 error.name === 'AbortError'- 不可重试
Gemini说这个:
const isRetriable = error.name !== 'AbortError' && /fetch|network|failed/i.test(error.message);
但它对无效的URL方案不起作用,因为它抛出这个错误,其消息中包含 fetch,但并不可重试。
TypeError: Failed to fetch. URL scheme "xhttps" is not supported.
at ...
如何在 catch 块内,检查 error 是否可重试?
解决方案
你想要像下面这样的吗?如果第一次尝试失败,就进行下一次,若不可重试则直接终止。
另外,为防止无限循环,增加了最大尝试次数
let url = "xhttp://example.com";
call(url);
async function call(url, attempt = 1, maxAttempts = 3) {
try {
const response = await fetch(url);
if (!response.ok) {
const retryableStatuses = [502, 503, 504];
if (retryableStatuses.includes(response.status)) {
console.log(`Server error ${response.status}. Retryable.`);
// force retry by throwing a custom error to the catch block
throw new Error(`HTTP_${response.status}`);
}
// 404 or 400, non-retryable. Stop here.
console.error(`Fatal HTTP error: ${response.status}`);
return;
}
// Success case
const data = await response.json().catch(() => null);
console.log("Success!", data);
} catch (error) {
// enforce max attempts to prevent infinite loops
if (attempt >= maxAttempts) {
console.error("Max retry attempts reached. Aborting.");
return;
}
if (error.message.startsWith('HTTP_') || isFetchErrorRetryable(error, url)) {
console.log(`Retrying attempt ${attempt + 1}...`);
// just as example, 1 retry with success
const nextUrl = 'https://httpbin.org/status/200';
await call(nextUrl, attempt + 1, maxAttempts);
} else {
console.error("Fatal error. Do not retry:", error.message);
}
}
}
function isFetchErrorRetryable(error, urlString) {
if (error.name === 'AbortError' || error.name === 'TimeoutError') {
return false;
}
try {
const parsedUrl = new URL(urlString);
if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {
return false;
}
} catch (urlError) {
return false;
}
if (error instanceof TypeError && !/failed to fetch|network/i.test(error.message)) {
return false;
}
return true;
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。