日常开发优先用 axios;fetch 默认 credentials 为 'omit'(不带 Cookie),axios 为 'same-origin'(同源自动带);fetch 对 4xx/5xx 不自动报错,需手动判断 res.ok,axios 默认抛错。

直接说结论:日常开发中优先用 axios,除非你明确需要轻量、无依赖或必须用原生 fetch 的场景(比如写浏览器扩展、做 polyfill、或团队强制规范)。
为什么 fetch 默认不带 Cookie,而 axios 默认带?
fetch 默认的 credentials 选项是 'omit',即不发送 Cookie 和认证头;axios 默认是 'same-origin'(同源时自动携带 Cookie)。这是最常踩的坑——登录态丢失、401 报错、接口返回空数据。
- 修复
fetch:调用时必须显式加{ credentials: 'include' } - 修复
axios:跨域需后端配合设置Access-Control-Allow-Credentials: true,且不能设Access-Control-Allow-Origin: *(必须指定具体域名) - 注意:即使加了
credentials: 'include',若后端没返回正确的 CORS 头,浏览器仍会静默拦截响应
如何统一处理 4xx/5xx 响应,而不是手动检查 status?
fetch 只在真正网络失败(如断网、DNS 错误)时 reject,HTTP 状态码 400、500 等仍算 “success”,需手动判断;axios 默认对非 2xx 状态码抛错,可直接进 catch。
fetch('/api/user')
.then(res => {
if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
return res.json();
})
.catch(err => console.error('请求失败:', err));
axios.get('/api/user')
.catch(err => {
// 400、500、网络错误都会进这里
console.error('请求失败:', err.response?.status, err.message);
});
-
fetch的res.ok等价于res.status >= 200 && res.status -
axios的err.response包含响应体,err.request是原始 XMLHttpRequest / fetch Request 对象,err.message描述错误类型 - 想让
fetch行为接近axios,建议封装一层,自动检查res.ok并throw
上传文件时 FormData 处理差异
两者都支持 FormData,但默认行为不同:fetch 不会自动设置 Content-Type 请求头(浏览器会自动设为 multipart/form-data; boundary=...);axios 若传入 FormData,会删掉你手动设的 Content-Type(避免冲突),由浏览器自动生成。
立即学习“Java免费学习笔记(深入)”;
- 用
fetch上传时,**不要手动设置Content-Type头**,否则边界符失效,后端收不到字段 - 用
axios上传时,也别设Content-Type,它内部已处理;若强行设成'multipart/form-data'(不带 boundary),后端大概率解析失败 - 进度监听:fetch 需靠
ReadableStream+progress事件(兼容性差);axios 原生支持onUploadProgress配置项
真正麻烦的不是选哪个库,而是混用时的隐性不一致:比如一个项目里部分用 fetch 封装了 request,部分用 axios,结果 401 处理逻辑分散、超时配置两套、错误消息格式不统一。选一个,配好拦截器/封装层,比反复纠结语法细节重要得多。










