axios 请求只报泛化 Network Error:如何为网络错误分类并输出详细原因
2026/9/9 22:42:28 网站建设 项目流程

axios 请求只报泛化 Network Error:如何为网络错误分类并输出详细原因

【免费下载链接】axiosPromise based HTTP client for the browser and node.js项目地址: https://gitcode.com/GitHub_Trending/ax/axios

axios 默认对大量不同的网络故障抛出同一个"Network Error"消息:断网、DNS 解析失败、服务器拒绝连接、CORS 拦截、请求超时,在catch里看起来几乎一样,调试时无法区分根因。本场景的目标是:在 axios 上挂一个响应拦截器,对错误做分类,给每个错误对象重写error.code(如ERR_TIMEOUTERR_DNS_FAILURE)并新增一个error.detailedMessage字段输出可读原因。仓库中的examples/improved-network-errors.mdexamples/network_enhanced.js提供了完整的方案与实现,按浏览器和 Node.js 两种环境均可使用。

前提只需安装 axios:

npm install axios

先弄清:为什么 axios 只报泛化错误

查阅 官方错误处理文档 的错误码表,与网络故障相关的有两个关键点:

  • ERR_NETWORK:网络类问题。在浏览器中,这个错误还可能由 CORS 或 Mixed Content 策略违规引起。文档明确指出:浏览器不允许 JS 代码澄清由安全问题引起的错误真实原因,需要自行查看控制台。
  • 超时默认报ECONNABORTED;只有设置transitional.clarifyTimeoutError: true后才会报ETIMEDOUT,这样超时错误才能和其他中断区分开。

也就是说,axios 本身的错误对象信息有限(浏览器安全限制决定了这一点),要输出详细原因,需要在业务层基于error.codeerror.message和响应状态码做二次分类。

方案:响应拦截器 + 错误增强函数

examples/improved-network-errors.md 描述的机制:

  1. axios.create(config)创建实例;
  2. 通过client.interceptors.response.use()注册响应拦截器,在拒绝分支里捕获错误(拦截器机制见 Interceptors 文档);
  3. 拦截器调用enhanceNetworkError(error):根据error.codeerror.messageerror.response.status判断错误类型,改写error.code,挂上新字段error.detailedMessage,然后重新throw出去。

完整实现见仓库中的 examples/network_enhanced.js,核心代码如下:

import axios from 'axios'; function enhanceNetworkError(error) { // when Offline (no internet) if (typeof navigator !== 'undefined' && !navigator.onLine) { error.code = 'ERR_NO_INTERNET'; error.detailedMessage = 'No internet connection detected. Please check your connection and try again.'; } // when DNS failure occurs (invalid domain) else if (error.code === 'ENOTFOUND' || /dns/i.test(error.message)) { error.code = 'ERR_DNS_FAILURE'; error.detailedMessage = 'Unable to reach the requested domain. Please verify the URL or your network settings.'; } // when Connection refused by server else if (error.code === 'ECONNREFUSED' || /refused/i.test(error.message)) { error.code = 'ERR_CONNECTION_REFUSED'; error.detailedMessage = 'Connection was refused by the server. It may be temporarily unavailable.'; } // when Request timeout happens else if (error.code === 'ETIMEDOUT' || /timeout/i.test(error.message)) { error.code = 'ERR_TIMEOUT'; error.detailedMessage = 'The request took too long to respond. Please try again later.'; } // when CORS restriction happens (for browser only) else if (/CORS/i.test(error.message)) { error.code = 'ERR_CORS_BLOCKED'; error.detailedMessage = 'The request was blocked due to cross-origin restrictions.'; } // when Server-side error occurs else if (error.response && error.response.status >= 500) { error.code = 'ERR_SERVER'; error.detailedMessage = 'A server-side issue occurred. Please try again later.'; } // when Client-side error occurs else if (error.response && error.response.status >= 400) { error.code = 'ERR_CLIENT'; error.detailedMessage = 'A client-side error occurred. Please check your request.'; } // when unknown network issue occurs else { error.code = 'ERR_NETWORK_GENERIC'; error.detailedMessage = 'A network issue occurred. Please check your connection or try again later.'; } return error; } export function createEnhancedClient(config = {}) { const client = axios.create(config); client.interceptors.response.use( (response) => response, (error) => { throw enhanceNetworkError(error); } ); return client; } export default enhanceNetworkError;

分类规则按if/else链的先后顺序匹配(先命中先归类):

判断条件归类 codedetailedMessage 含义
navigator.onLinefalse(浏览器)ERR_NO_INTERNET无网络连接
error.code === 'ENOTFOUND'或 message 含dnsERR_DNS_FAILURE域名无法解析
error.code === 'ECONNREFUSED'或 message 含refusedERR_CONNECTION_REFUSED服务器拒绝连接
error.code === 'ETIMEDOUT'或 message 含timeoutERR_TIMEOUT请求超时
message 含CORS(浏览器)ERR_CORS_BLOCKED跨域被拦截
error.response.status >= 500ERR_SERVER服务端错误
error.response.status >= 400ERR_CLIENT客户端错误
以上都不满足ERR_NETWORK_GENERIC未识别的网络问题

注意 5xx 的判断在 4xx 之前,因此 500 以上归类为ERR_SERVER,400–499 归类为ERR_CLIENT

使用与验证

createEnhancedClient()创建客户端即可,之后所有请求的错误都会带上分类信息。以下示例中的baseURL是文档示例值,替换为你自己的接口地址:

const api = createEnhancedClient({ baseURL: 'https://example.com' }); api .get('/data') .then((res) => console.log(res.data)) .catch((err) => { console.error(err.code); // e.g., ERR_TIMEOUT console.error(err.detailedMessage); // e.g., "The request took too long to respond." });

验证方式:发起一个必然失败的请求(超时、错误域名、断网均可),在catch中打印err.codeerr.detailedMessage,能按上表输出对应分类即说明拦截器生效。上面代码块中的两个// e.g.,值是文档给出的示例输出,不是固定预期。

若想在分类前先检查 axios 原始错误,错误处理文档 给出了三分支判断:error.response存在表示服务器已响应但状态码不在 2xx 范围;error.request存在表示请求已发出但没有收到响应(浏览器中是XMLHttpRequest实例,Node.js 中是http.ClientRequest实例);两者都没有则是请求设置阶段出错。错误对象还支持error.toJSON()获取完整信息,含messagenamestackconfigcodestatus字段。

让超时错误可靠命中超时分支

enhanceNetworkError的超时分支依赖ETIMEDOUT(或 message 含timeout)。而 axios 默认超时报的是ECONNABORTED。按 官方超时处理文档,应在请求配置(或createEnhancedClient传入的 config)中设置timeout并开启clarifyTimeoutError

const response = await axios.get("https://example.com/data", { timeout: 5000, // 5 seconds transitional: { // set to true if you prefer ETIMEDOUT over ECONNABORTED clarifyTimeoutError: true, }, });

官方文档同时提示:生产环境应始终设置timeout,否则卡住的请求可能无限挂起。clarifyTimeoutError的含义与默认值(false)见 request-config 文档。

限制与边界

  • 浏览器中的 CORS/Mixed Content 无法可靠识别:官方文档明确说明浏览器不允许 JS 代码澄清这类安全错误的真实原因,要定位需查看控制台。/CORS/i.test(error.message)这条规则只在错误 message 中确实含有CORS字样时才命中,不能保证覆盖所有跨域失败。
  • 离线检测只在浏览器生效ERR_NO_INTERNET分支依赖navigator.onLine,Node.js 环境中该分支不成立,断网会落到后续规则或ERR_NETWORK_GENERIC
  • 分类顺序固定if/else链保证先命中的规则优先(如离线判断在 DNS 判断之前),不要随意调整顺序。
  • 该方案是业务层封装:它改写的是你应用持有的错误对象,axios 抛出的原始错误(ERR_NETWORKECONNABORTED等)行为不变,其他使用 axios 的模块不受此拦截器影响。

参考文件

  • examples/improved-network-errors.md:问题描述、分类映射与用法示例
  • examples/network_enhanced.js:enhanceNetworkErrorcreateEnhancedClient完整实现
  • docs/pages/advanced/error-handling.md:axios 官方错误结构、错误码表与超时处理
  • docs/pages/advanced/interceptors.md:拦截器机制与执行顺序
  • docs/pages/advanced/request-config.md:timeouttransitional.clarifyTimeoutError配置说明

【免费下载链接】axiosPromise based HTTP client for the browser and node.js项目地址: https://gitcode.com/GitHub_Trending/ax/axios

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询