Fetch API 是浏览器原生提供的基于 Promise 的网络请求接口,替代了传统 XHR 的回调模式。一个最简单的 GET 请求如下:
fetch('https://api.example.com/data')
.then(response => response.json()) // 解析 JSON 数据
.then(data => console.log(data))
.catch(error => console.error('请求失败:', error));
fetch() 返回一个 Promise,该 Promise 在收到响应头后立即 resolve(无论 HTTP 状态码是否为 2xx),因此需要手动检查 response.ok 或状态码来处理业务错误:
fetch('https://api.example.com/data')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP 错误! 状态码: ${response.status}`);
}
return response.json();
})
.then(data => console.log(data))
.catch(error => console.error('请求失败:', error));
Response 对象提供了多种读取数据的方法:json()、text()、blob()、formData()、arrayBuffer(),这些方法都返回 Promise。
16.2.2 配置项
fetch() 的第二个参数是一个可选的配置对象,用于定制请求行为。常用配置项如下:
fetch('https://api.example.com/data', {
method: 'POST', // 请求方法:GET, POST, PUT, DELETE 等
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer token123'
},
body: JSON.stringify({ key: 'value' }), // 请求体,GET/HEAD 不能设置 body
mode: 'cors', // 请求模式:same-origin, cors, no-cors
credentials: 'include', // 是否携带 cookie:omit, same-origin, include
cache: 'default', // 缓存模式:no-cache, reload, force-cache 等
redirect: 'follow', // 重定向处理:follow, error, manual
referrerPolicy: 'no-referrer-when-downgrade' // 引用来源策略
})
关键配置项说明:
- method:字符串,默认 'GET',大小写不敏感但建议大写。
- headers:Headers 对象或普通对象,用于设置请求头。
- body:请求体数据,支持字符串、FormData、Blob、URLSearchParams 等。若发送 JSON,需手动调用
JSON.stringify()并设置Content-Type。 - mode:控制跨域行为,
'cors'表示允许跨域但需遵守 CORS 协议,'same-origin'仅同源请求,'no-cors'用于带有 opaque 响应的简单请求。 - credentials:控制 Cookie 和认证信息,
'same-origin'仅同源携带,'include'跨域也携带,'omit'不携带。注意跨域携带 Cookie 时,服务器必须返回Access-Control-Allow-Credentials: true。 - cache:缓存策略,与 Service Worker 配合使用更精细。
16.2.3 与 XHR 的差异
| 对比维度 | XHR | Fetch API |
|----------|-----|-----------|
| 语法风格 | 基于事件回调(onload、onerror),容易陷入回调地狱 | 基于 Promise,支持链式调用和 async/await,可读性更好 |
| 请求取消 | xhr.abort() 原生支持 | 需配合 AbortController 实现(稍显复杂) |
| 上传/下载进度 | 支持 xhr.upload.onprogress | 浏览器暂未提供下载进度事件(需通过 ReadableStream 自行处理) |
| 跨域 Cookie | 默认携带同源 Cookie,可通过 withCredentials 携带跨域 Cookie | 默认不携带任何 Cookie(credentials: 'omit'),需显式设置 credentials: 'include' |
| 错误处理 | onerror 事件,40x/50x 状态码也会触发 onload,需手动判断 | 只有网络错误才会使 Promise reject,HTTP 错误状态码(如 404、500)不会 reject,需检查 response.ok |
| 超时设置 | 支持 xhr.timeout 属性 | 无内置超时,需结合 AbortController 或 Promise.race 实现 |
| 响应类型 | 通过 xhr.responseType 指定(text, json, blob 等) | Response 对象提供 json()、text() 等方法,更统一但均为异步 |
| 浏览器兼容性 | 所有浏览器均支持 | 现代浏览器完全支持,IE 需 polyfill |
总结: Fetch 提供了更现代、更简洁的接口,是 HTTP 请求的主流方案。但某些场景下(如需要进度监控或更简单的超时取消),XHR 可能更直接。实际开发中,通常会使用 Axios 等封装库,结合两者优势并弥补各自的不足。