主题
Fetch
fetch 是现代浏览器中最常用的网络请求接口。它基于 Promise,和 Request、Response、Headers 一起构成了较完整的请求模型。
Fetch 的定位
相比 XMLHttpRequest,fetch 的特点主要有:
- API 更简洁
- 天然使用 Promise
- 响应体支持流式读取
- 更适合和
Request/Response/AbortController组合
它已经是大多数前端项目默认的请求基础能力。
最基础的 GET 请求
js
fetch('/api/items')
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP ${response.status}`)
}
return response.json()
})
.then((data) => {
console.log(data)
})
.catch((error) => {
console.error(error)
})最基础的 POST 请求
js
fetch('/api/items', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'New Item',
}),
})
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP ${response.status}`)
}
return response.json()
})
.then((data) => {
console.log(data)
})常用读取方式
拿到响应对象后,通常还要按内容类型读取响应体。
js
const response = await fetch('/api/items')常见方法:
response.json()response.text()response.blob()response.arrayBuffer()response.formData()
一个重要特点
fetch 不会因为 404、500 自动进入 catch。只有真正的网络失败才会 reject。
所以业务里通常要主动判断:
js
if (!response.ok) {
throw new Error(`HTTP ${response.status}`)
}发送不同类型的请求体
发送 JSON
js
fetch('/api/items', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: 'Tom' }),
})发送 FormData
js
const formData = new FormData()
formData.append('file', file)
fetch('/upload', {
method: 'POST',
body: formData,
})使用 FormData 时,不要手动设置 Content-Type。
和 XHR 的对比
| 功能点 | XHR | Fetch |
|---|---|---|
| 基本请求能力 | ✅ | ✅ |
| Promise 风格 | ❌ | ✅ |
| 请求取消 | ✅ | ✅ |
| 流式处理 | ❌ | ✅ |
| 读取下载进度 | ✅ | 需结合流处理 |
| 传统兼容性 | 更好 | 较新 |
适合什么场景
- 常规接口请求
- 和
async/await配合 - 需要
AbortController - 需要和
Request/Response/Service Worker协作
什么时候还会看到 XHR
- 老项目
- 上传下载进度依赖 XHR 事件模型
- 某些兼容性要求较强的场景
