javascript如何请求API_fetch和axios如何使用【教程】

fetch和axios默认行为差异大:fetch不带cookie、4xx/5xx不reject、需手动检查res.ok并设credentials: 'include';axios自动reject异常但默认也不带cookie,需withCredentials: true;取消机制、超时、文件上传等均不同,混用易致静默失败。

fetch 和 axios 都能发请求,但默认行为、错误处理、取消机制完全不同

——别直接替换用,否则线上会静默失败。

fetch 默认不带 cookie,401/403 错误不会自动 reject

fetch 的 response.ok 只判断 HTTP 状态码是否在 200–299,401403500 都算“成功”返回,必须手动检查:

fetch('/api/user', {
  credentials: 'include' // 不加这行,带 cookie 的接口必 401
})
.then(res => {
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
})
.catch(err => console.error(err)); // 这里才真正捕获认证失败
  • credentials: 'include' 必须显式声明,否则跨域请求不带 cookie
  • 网络中断、DNS 失败等底层错误才会进 catch;服务端返回 4xx/5xx 仍走 then
  • 没有内置超时,需用 AbortController 手动控制

axios 自动抛出 4xx/5xx 错误,但默认不发 cookie

axios 把 401 当作异常直接进 catch,更符合直觉,但默认仍不携带 cookie:

axios.get('/api/user', {
  withCredentials: true // 注意:不是 credentials,是 withCredentials
})
.catch(err => {
  if (err.response?.status === 401) {
    // 这里能稳定捕获登录过期
  }
});
  • withCredentials: true 是 axios 的写法,和 fetch 的 credentials 不兼容
  • err.response 存响应体,err.request 存原生 XMLHttpRequest 实例
  • axios 0.27+ 支持 signal(同 AbortController),老版本只能靠 CancelToken(已弃用)

上传文件时,fetch 要手动构造 FormData,axios 会自动处理

FileBlob 时,fetch 必须显式包装,axios 则直接传对象即可:

// fetch:必须自己 new FormData()
const formData = new FormData();
formData.append('file', fileInput.files[0]);
fetch('/upload', {
  method: 'POST',
  body: formData // 不能加 headers: {'Content-Type': 'multipart/form-data'},浏览器会自设 boundary
});

// axios:直接传对象,它内部转 FormData
axios.post('/upload', { file: fileInput.files[0] });
  • fetch 加了手动 Content-Type 头反而会破坏 boundary,导致后端解析失败
  • axios 在非 multipart/form-data 场景下(如 JSON)仍默认加 Content-Type: application/json
  • 大文件上传进度监听:fetch 用 upload.onprogress,axios 用 onUploadProgress 配置项

取消请求的写法差异极大,别混用 AbortController 和 CancelToken

现代浏览器中,fetch 用 AbortController 是标准方案;axios 从 0.27 开始也支持它,但旧项目可能还在用已废弃的 CancelToken

// fetch 标准取消
const controller = new AbortController();
fetch('/api/data', { signal: controller.signal });
controller.abort(); // 立即触发 TypeError: cancelled

// axios 新写法(推荐)
const controller = new AbortController();
axios.get('/api/data', { signal: controller.signal });
controller.abort();

// axios 旧写法(避免新增)
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.get('/api/data', { cancelToken: source.token });
source.cancel(); // 触发 Cancel 错误
  • 两种 cancel 机制互不兼容,AbortController 的 error 是 DOMExceptionCancelTokenCancel 实例
  • React 中清理副作用时,务必在组件卸载前调用 abort(),否则可能触发内存泄漏警告
  • 多个并发请求共用一个 AbortController 时,abort 会一并取消全部

真正麻烦的是混合场景:比如用 fetch 封装的工具函数里忘了加 credentials: 'include',又在 axios 请求里漏了 withCredentials: true,两边都拿不到 session,但错误表现一模一样——全是 401,还查不出为什么。