Fetch API 是浏览器原生网络请求接口,基于 Promise 设计,不自动处理 HTTP 错误;4xx/5xx 状态码不会触发 reject,需手动检查 response.ok 或 status。

Fetch API 是浏览器原生提供的、用于发起网络请求的现代 JavaScript 接口;它不是 XMLHttpRequest 的升级版,而是设计哲学完全不同的替代方案——默认基于 Promise,不自动处理 HTTP 错误状态码,也不共享 cookie(除非显式配置)。
Fetch 默认不把 4xx/5xx 当作 reject
这是最常踩的坑:用 fetch() 请求一个返回 404 的 URL,then() 依然会执行,因为只要网络层通了、响应头收到了,Promise 就算 fulfilled。你得手动检查 response.ok 或 response.status。
fetch('/api/user/999')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
return response.json();
})
.catch(err => console.error(err));
-
response.ok等价于response.status >= 200 && response.status -
XMLHttpRequest在 4xx/5xx 时不会触发onerror,但会进onload,同样需要手动判断status - 区别在于:Fetch 把“网络失败”和“HTTP 错误”明确区分开,前者 reject,后者 resolve
Fetch 不支持 progress 事件,也无法中止正在传输的 body
上传大文件或需要实时显示下载进度时,XMLHttpRequest 的 upload.onprogress 和 download.onprogress 仍是不可替代的。Fetch 没有等效机制;虽可用 AbortController 中止整个请求,但无法在流式读取过程中暂停或监听已接收字节数。
-
fetch()支持signal参数配合AbortController实现超时或取消,但仅作用于请求发起阶段或未开始读取时 - 要监听进度,必须退回到
XMLHttpRequest,或用ReadableStream+tee()自行分块读取(复杂且不兼容旧浏览器) - 服务端流式响应(如 SSE、text/event-stream)可配合
response.body.getReader()逐段处理,但无内置进度百分比
Fetch 的 credentials 行为默认更严格
默认情况下,fetch() 不发送 cookies,也不携带认证头(如 Authorization),即使目标域名与当前页面同源。这和 XMLHttpRequest 的默认行为一致,但开发者常常忽略这点,导致登录态丢失。
立即学习“Java免费学习笔记(深入)”;
fetch('/api/profile', {
credentials: 'include' // 必须显式声明
});
-
credentials: 'include':发送 cookies 和认证头(需服务端设置Access-Control-Allow-Credentials: true) -
credentials: 'same-origin':默认值,只在同源时发(但很多人误以为是“自动同源”) -
credentials: 'omit':从不发送(类似XMLHttpRequest.withCredentials = false) -
XMLHttpRequest的withCredentials默认为false,行为其实一致,只是 Fetch 的默认值名更易误导
真正难处理的不是语法差异,而是 Fetch 把错误分类、凭据策略、流控制这些原本隐含在 XHR 里的行为全部暴露成显式配置项——写对容易,写全、写稳、覆盖边界场景,反而更费神。











