Fetch API 是现代浏览器发起 HTTP 请求的首选方式,基于 Promise 且更简洁;但仅网络失败时 reject,404/500 等状态码仍 resolve,需手动检查 res.ok 或 status;超时与取消需配合 AbortController 使用。

Fetch API 是浏览器原生提供的、用于发起网络请求的现代接口,它比 XMLHttpRequest 更简洁、更基于 Promise,是当前 JavaScript 发起 HTTP 请求的首选方式。
fetch() 基本用法和常见错误
调用 fetch() 返回一个 Promise,但要注意:它只在**网络失败(如断网、DNS 错误)时 reject**,而 HTTP 状态码如 404、500 仍会 resolve。这是最容易踩坑的地方。
常见错误现象:fetch('/api/user').then(res => console.log(res.status)) 输出 404 却不报错,后续逻辑照常执行,导致数据解析失败或 UI 异常。
- 必须手动检查
res.ok(等价于res.status >= 200 && res.status ) - 不要直接对
fetch()调用.catch()来捕获 4xx/5xx 错误 - 响应体需显式调用
res.json()、res.text()等方法读取,且每个只能调用一次
GET 和 POST 请求的写法差异
GET 请求通常只需传入 URL 字符串;POST 则必须配置 method、headers 和 body,且 body 类型决定后端接收方式。
立即学习“Java免费学习笔记(深入)”;
发送 JSON 数据时,Content-Type 必须设为 'application/json',否则后端可能无法解析;发送表单数据则应使用 FormData 对象,此时浏览器自动设置正确的 Content-Type(含 boundary)。
fetch('/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: 'admin', password: '123' })
})
const form = new FormData();
form.append('file', fileInput.files[0]);
fetch('/upload', {
method: 'POST',
body: form // 不要设 headers,让浏览器自动处理
})
如何处理认证和跨域请求
携带 Cookie 需显式设置 credentials: 'include',否则默认不发送;同时服务端必须响应 Access-Control-Allow-Credentials: true,且 Access-Control-Allow-Origin 不能为通配符 *。
Token 认证一般通过 Authorization 请求头传递:
headers: { 'Authorization': 'Bearer ' + token }- 若使用
credentials: 'include',注意它与Authorization头可共存,但某些代理或 CDN 可能过滤该头 - 开发时遇到 CORS 报错,先确认预检请求(OPTIONS)是否被正确响应,而不是只看主请求
超时和取消请求怎么实现
Fetch 本身不支持超时或取消,需借助 AbortController 实现。它不是模拟取消,而是真正中止底层连接(从 Chrome 89+ 开始生效)。
超时逻辑必须在 Promise race 中封装,且 abort() 后仍需处理已 resolve 的响应(避免未 catch 的 promise rejection)。
const controller = new AbortController();
setTimeout(() => controller.abort(), 5000);
fetch('/api/data', { signal: controller.signal })
.then(res => {
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
})
.catch(err => {
if (err.name === 'AbortError') {
console.log('请求超时');
} else {
console.error('请求失败:', err);
}
});
多个并发请求共用一个 AbortController 时,调用 abort() 会全部取消——这点容易被忽略,实际项目中建议按业务粒度独立创建控制器。










