fetch()是现代JavaScript发送HTTP请求的首选,但需手动检查response.ok;XMLHttpRequest适用于进度监听和中止请求;axios解决fetch痛点且支持AbortController取消请求。
绝大多数新项目应直接用 fetch(),它基于 Promise、语法简洁、原生支持 CORS 和流式响应。但要注意:它默认不带 Cookie,且 4xx/5xx 状态码不会触发 reject——这和很多人直觉相反。
常见错误现象:fetch('/api/user') 返回 404 时代码仍进入 .then(),导致后续解析 response.json() 报错 Unexpected end of JSON input。
response.ok 或 response.status 才能区分成功与业务失败{ credentials: 'include' }
headers: { 'Content-Type': 'application/json' }
fetch(),如需兼容,得引入 polyfill 或改用 XMLHttpRequest
XMLHttpRequest 虽然繁琐,但它支持上传进度监听、请求中止(abort())、同步请求(不推荐)、以及更细粒度的 readyState 控制。当你遇到“上传大文件时想显示进度条”或“用户点了取消就立刻中断请求”,XMLHttpRequest 是唯一可靠选择。
典型陷阱:xhr.onreadystatechange 回调里没判断 xhr.readyState === 4 就直接读 xhr.responseText,结果拿到空值或中间状态。
if (xhr.readyState === 4) 内处理响应xhr.addEventListener('load', handler) 比 onreadystatechange 更清晰open() 后、send() 前赋值 xhr.timeout = 10000
async: false)会阻塞主线程,已在现代浏览器中被弃用如果你的项目允许引入第三方依赖,axios 解决了 fetch() 的多数痛点:自动抛出异常、默认携带 Cookie、请求/响应拦截器、取消请求能力(CancelToken 或 AbortController)、以及更友好的错误结构。
注意版本差异:v0.27+ 开始原生支持 AbortController,旧版用 CancelToken.source();配置项如 baseURL、timeout、

withCredentials 都是常用且易配错的地方。
axios.defaults.withCredentials = true,可能意外泄露凭证到第三方域名config,否则请求会消失axios.get(url, { params: { id: 1 } }) 自动拼 query,但 axios.post(url, data) 默认以 JSON 形式提交用户跳转页面、输入框快速连打、弹窗关闭等场景下,未完成的请求若继续执行并更新状态,极易引发竞态 bug(比如后发的请求先返回,覆盖了最新数据)。AbortController 是统一解决方案,fetch()、axios(v0.22+)、甚至 XMLHttpRequest(通过 xhr.signal)都支持。
容易被忽略的一点:控制器实例不能复用。每次请求都应新建 new AbortController(),然后把 signal 传入请求选项。组件卸载时调用 controller.abort() 即可。
useEffect 清理函数使用onBeforeUnmount 同理AbortController,abort 后信号不可重用