Fetch API 是浏览器原生提供的、基于 Promise 的现代网络请求接口。相比老旧的 XMLHttpRequest(XHR),它将请求与响应抽象为更清晰的 Request 和 Response 对象,并使用 Promise 管理流程,避免了回调嵌套,代码可读性大幅提升。
基本用法
最基础的 GET 请求只需要一行:
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(err => console.error('请求失败', err));
如果需要 POST JSON 数据,可以配置第二个参数:
fetch('https://api.example.com/submit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: '张三', age: 25 })
})
.then(response => response.json())
.then(data => console.log('成功', data))
.catch(err => console.error('失败', err));
核心配置项
fetch(input, init) 的第二个参数 init 是一个配置对象,常用选项如下:
- method:请求方法,如
GET、POST、PUT、DELETE,默认GET。 - headers:请求头对象,既可以是普通字面量,也可以通过
new Headers()构建。 - body:请求体,用于
POST/PUT等,可以是字符串、FormData、Blob、URLSearchParams 等。 - mode:跨域模式,如
cors(默认,允许跨域但需服务器配合)、no-cors、same-origin。 - credentials:是否携带 Cookie,
include(携带)、same-origin(默认,同源携带)、omit。 - signal:关联
AbortController,用于取消请求。
与 XHR 的核心差异
| 特性 | XMLHttpRequest | Fetch API |
|------|---------------|-----------|
| 异步模型 | 基于事件回调 (onload、onerror) | 基于 Promise,支持链式调用与 async/await |
| 请求取消 | xhr.abort() | 通过 AbortController.signal 传入 |
| 进度监听 | 支持 xhr.upload.onprogress | 原生不支持上传进度(需借助流式接口) |
| 接收流数据 | 不支持 | 支持 response.body 可读流,适合大文件下载 |
| 超时设置 | 内置 xhr.timeout | 无内置超时,需自行通过 AbortController 或 Promise.race 模拟 |
| 跨域 Cookie | 默认携带同源 Cookie | 默认不携带,需显式设置 credentials: 'include' |
使用 async/await 后的 Fetch 代码与同步写法几乎一致:
async function getUser() {
const response = await fetch('/api/user');
if (!response.ok) throw new Error('接口返回错误');
return response.json();
}
不可忽视的局限性
- 只对网络错误 reject
HTTP 状态码 4xx、5xx 不会让 fetch 走到 catch,必须手动检查 response.ok 或 response.status。这是很多初学者的坑点。
- 不支持超时控制
原生的 fetch 没有超时选项,必须通过 AbortController 配合 setTimeout 来实现:
const controller = new AbortController();
setTimeout(() => controller.abort(), 5000);
fetch('/api/data', { signal: controller.signal })
.catch(err => { if (err.name === 'AbortError') console.log('请求超时取消'); });
- 无法监听上传进度
文件上传时如果需要进度条,fetch 目前无法直接提供 upload progress,只能退回到 XHR 或使用 Service Worker 流处理(不常用)。
- 默认不携带 Cookie
出于安全考虑,同源请求也需要显式指定 credentials: 'include' 才会发送 Cookie,否则响应中的 Set-Cookie 可能被忽略。
- 兼容性中等
Fetch API 已在所有现代浏览器中落地,但 IE 完全不支持(需要使用 polyfill),部分老版本 Android WebView 也有缺失。
实用建议
- 在实际项目中,常常对 fetch 做一层简易封装,统一处理错误、添加超时、自动 JSON 解析、基础鉴权等。
- 对于需要上传进度、兼容旧浏览器或需要更复杂功能的场景,推荐使用经过社区检验的库(如 Axios),它们内部封装了大量细节,让开发更高效稳健。
Fetch API 在现代 Web 开发中已经是基础能力,理解它的特性与局限,能帮助你写出更健壮的网络请求代码,也为理解 Axios 等上层封装打下基础。