404错误是服务器明确返回的“资源不存在”响应,不属于可重试错误,应在获取响应后立即排除,仅对502/503/504等临时性服务端错误或网络异常(如TypeError)触发重试。

404 错误本身不是网络异常,而是服务器明确返回的“资源不存在”响应,它不会导致 fetch 拒绝 Promise,所以**不能也不该被纳入自动重试范围**。盲目重试 404 不仅无效,还会浪费请求、干扰监控、甚至暴露探测行为。关键在于:区分“可重试错误”和“终态错误”,把 404 归为后者,直接跳过重试逻辑。
明确哪些错误才值得重试
只有临时性、非业务语义的失败才适合重试,比如:
- 网络中断、DNS 失败、连接被拒绝(
err.name === 'TypeError') - 网关超时、服务不可用(HTTP 状态码 502 / 503 / 504)
- AbortError(由
AbortController主动中止,常因超时)
而 404、401、403、410 等是服务器主动告知客户端“你找错了”或“你没权限”,属于确定性结果,重试毫无意义。
在重试函数中过滤掉 404
不要等整个请求链路走完再判断——要在拿到响应后、决定是否重试前,就排除 404。推荐写法:
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 先用
await fetch()获取响应对象 - 检查
response.ok或response.status - 若状态码是 404,直接
return response(不抛错,也不重试) - 只对
!res.ok && [502,503,504].includes(res.status)这类情况触发重试
示例逻辑片段:
if (!res.ok) {
if (res.status === 404) return res; // 终态,不重试
if ([502, 503, 504].includes(res.status)) {
// 触发下一次重试
} else {
throw new Error(`HTTP ${res.status}`);
}
}
避免 404 被误判为网络错误
常见误区是把 fetch 的 catch 块当成“所有错误入口”,但 404 不会进这里。它只捕获真正失败的请求(如离线、跨域拒绝、CORS 错误)。因此:
- 不要在
catch里处理 404 —— 它根本不会进来 - 404 必须在
then分支中,通过response.status或response.ok显式识别 - 如果想统一处理“失败响应”,建议封装一个
handleResponse函数,在其中做状态码分流
结合 shouldRetry 判断函数更灵活
把重试策略抽成独立函数,便于复用和测试:
const shouldRetry = (err, res) => {
if (err?.name === 'TypeError') return true; // 网络断开
if (res && [502, 503, 504].includes(res.status)) return true;
return false;
};
// 在重试循环中调用:
if (shouldRetry(err, res)) {
// 执行延迟重试
} else {
throw err || new Error(`Non-retryable: ${res?.status || 'unknown'}`);
}
这样,404 响应自然被排除在外,逻辑清晰,后续加新规则也方便。

















