JavaScript Fetch API + HTTP 网络请求(权威)

本文是 JavaScript Fetch API + HTTP 网络请求 权威教程,涵盖 GET/POST/PUT/DELETE、响应处理、错误捕获、取消请求、async/await 最佳实践。
一、开篇:Fetch 是什么?
JavaScript 如何从服务器获取数据?如何加载用户信息、提交表单、拉取最新列表?答案就是:Fetch API——JS 现代网络请求标准。
// 最基础的 Fetch 请求
const response = await fetch('https://api.example.com/users/1')
const user = await response.json()
console.log(user.name) // "Alice"
学习本文前你需要掌握:Promise、async/await(Fetch 基于 Promise 实现)。
二、HTTP 基础(必须懂)
什么是 HTTP?
HTTP(超文本传输协议)是 Web 数据通信的基础。它是客户端 ↔ 服务器之间的消息格式与传输规则。
HTTP 与语言无关,Python/Java/JS 都使用它。
请求 - 响应模型(餐厅类比)
- 你(客户端) 点餐 → 请求(Request)
- 服务员(网络) 传给厨房
- 厨房(服务器) 处理
- 服务员把菜给你 → 响应(Response)
三、5 个最常用 HTTP 方法
| 方法 | 作用 | 类比 |
|---|---|---|
| GET | 获取数据 | 看菜单 |
| POST | 创建数据 | 下单 |
| PUT | 整体替换数据 | 换菜 |
| PATCH | 部分更新数据 | 加配料 |
| DELETE | 删除数据 | 取消订单 |
// GET
fetch('/api/users/123')
// POST
fetch('/api/users', {
method: 'POST',
body: JSON.stringify({ name: 'Alice' }),
headers: { 'Content-Type': 'application/json' }
})
四、HTTP 状态码(速记)
- 2xx(成功):200 OK、201 创建成功、204 无内容
- 3xx(重定向):301/302/304 缓存
- 4xx(客户端错):400 参数错、401 未登录、403 无权、404 不存在
- 5xx(服务端错):500 服务器崩溃、503 服务不可用
口诀:2xx 成了、3xx 挪了、4xx 你错了、5xx 他炸了。
五、Fetch API 是什么?
JS 原生现代网络请求 API,替代老旧的 XMLHttpRequest(XHR)。
优点:
- Promise 化
- 支持 async/await
- 流式响应
- 标准化 Request/Response
- 现代浏览器全支持
六、Fetch 基础使用
1)GET 请求(最简)
async function getUsers() {
const res = await fetch('/api/users')
const data = await res.json()
return data
}
2)POST 请求(提交 JSON)
async function createUser(user) {
const res = await fetch('/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(user)
})
return res.json()
}
3)Response 对象常用属性
res.status // 200 / 404 / 500
res.ok // 200~299 → true
res.statusText // "OK" / "Not Found"
res.headers // 响应头
res.url // 最终URL
4)解析响应体(都是 Promise)
await res.json() // JSON
await res.text() // 纯文本
await res.blob() // 文件/二进制
await res.formData() // 表单
await res.arrayBuffer() // 缓冲区
⚠️ 重要:响应体只能读一次,多次读取需用 res.clone()。
七、Fetch 最容易犯的错误(99% 人中招)
❌ 错误:以为 try/catch 能捕获 404/500
Fetch 只有网络错误才会 reject!404、500 属于成功的响应,不会进 catch。
// ❌ 错误:404/500 不会被捕获
try {
const res = await fetch('/api/bad')
const data = await res.json()
} catch (err) {
// 只有断网/CORS/超时才会进来
}
✅ 正确:必须判断 res.ok
const res = await fetch(url)
if (!res.ok) {
throw new Error(`HTTP 错误 ${res.status}`)
}
const data = await res.json()
八、超实用封装:fetchJSON
async function fetchJSON(url, options = {}) {
const res = await fetch(url, {
headers: { 'Content-Type': 'application/json', ...options.headers },
...options
})
if (!res.ok) {
const err = new Error(`HTTP ${res.status}`)
err.status = res.status
throw err
}
return res.status === 204 ? null : res.json()
}
九、并行请求(提速关键)
// ✅ 并行(快)
const [users, posts] = await Promise.all([
fetch('/api/users').then(r => r.json()),
fetch('/api/posts').then(r => r.json())
])
十、取消请求:AbortController
用于:
- 超时取消
- 页面离开取消
- 搜索防抖(取消上一次请求)
使用步骤
- 创建控制器
- 传入 signal
- 调用 abort ()
const controller = new AbortController()
fetch('/api/slow', { signal: controller.signal })
.catch(err => {
if (err.name === 'AbortError') console.log('已取消')
})
// 5秒后取消
setTimeout(() => controller.abort(), 5000)
搜索防抖(高频实战)
let prevController = null
async function search(q) {
if (prevController) prevController.abort()
const ctrl = new AbortController()
prevController = ctrl
const res = await fetch(`/api/search?q=${q}`, { signal: ctrl.signal })
return res.json()
}
十一、超时封装(必备)
async function fetchWithTimeout(url, opts = {}, ms = 5000) {
const ctrl = new AbortController()
const timer = setTimeout(() => ctrl.abort(), ms)
try {
const res = await fetch(url, { ...opts, signal: ctrl.signal })
clearTimeout(timer)
return res
} catch (err) {
clearTimeout(timer)
throw err
}
}
十二、核心总结(必背)
- Fetch 是现代 Promise 化请求 API
- 默认 GET
- 必须判断 res.ok 才能捕获 4xx/5xx
- 响应体要 await 解析
- 网络错误才进 catch
- AbortController 用于取消请求
- Promise.all 做并行请求
- 永远不要手动拼接 URL 参数,用
URLSearchParams
构建带加载状态的请求模式(真实项目必备)
在实际应用里,你通常需要同时管理 加载中 / 成功 / 失败 三种状态:
async function fetchWithState(url) {
const state = {
data: null,
loading: true,
error: null
}
try {
const response = await fetch(url)
if (!response.ok) throw new Error(`HTTP ${response.status}`)
state.data = await response.json()
} catch (err) {
state.error = err.message
} finally {
state.loading = false
}
return state
}
如何取消请求(AbortController)
适用场景
- 请求超时
- 用户离开页面
- 搜索框连续输入(取消上一次请求)
- 组件卸载(React/Vue)
完整工作流程
- 创建
AbortController实例 - 将
controller.signal传给 fetch - 调用
controller.abort()取消请求 - catch 会捕获
AbortError
完整代码示例
const controller = new AbortController()
fetch("/api/data", { signal: controller.signal })
.then(res => res.json())
.catch(err => {
if (err.name === "AbortError") {
console.log("请求已取消")
}
})
// 手动取消
controller.abort()
超时封装
async function fetchWithTimeout(url, options = {}, timeout = 5000) {
const controller = new AbortController()
const timer = setTimeout(() => controller.abort(), timeout)
try {
const res = await fetch(url, {
...options,
signal: controller.signal
})
clearTimeout(timer)
return res
} catch (err) {
clearTimeout(timer)
if (err.name === "AbortError") {
throw new Error(`请求超时 ${timeout}ms`)
}
throw err
}
}
搜索输入防抖(完整版)
let currentController = null
async function searchUsers(keyword) {
// 取消上一次请求
if (currentController) currentController.abort()
const ctrl = new AbortController()
currentController = ctrl
try {
const res = await fetch(`/api/search?q=${keyword}`, {
signal: ctrl.signal
})
if (!res.ok) throw new Error("请求失败")
return await res.json()
} catch (err) {
if (err.name === "AbortError") return null
throw err
}
}
知识测验(完整版)
Q1:网络错误与 HTTP 错误的区别
网络错误:断网、DNS 失败、CORS、连接失败 → Promise 拒绝(进入 catch)HTTP 错误:404/500 → Promise 已完成,必须判断 response.ok
Q2:为什么 response.json() 返回 Promise?
因为响应体是流(stream),需要异步完整读取后才能解析成 JSON。
Q3:POST 发送 JSON 必须做哪三件事?
method: 'POST'headers: { 'Content-Type': 'application/json' }body: JSON.stringify(data)
Q4:response.ok 是什么意思?
状态码 200~299 为 true,否则 false。
Q5:如何取消 fetch?
使用 AbortController,传入 signal,调用 abort()。
Q6:如何并行发送多个请求?
使用 Promise.all(),并发执行,速度远快于串行。
常见问题 FAQ(完整版)
Q:Fetch API 是什么?
JS 原生现代 HTTP 请求接口,基于 Promise,替代 XMLHttpRequest,所有现代浏览器与 Node.js 18+ 支持。
Q:fetch 与 XMLHttpRequest 有什么区别?
- fetch:Promise、简洁、支持流、现代标准
- XHR:回调、繁琐、老项目兼容
Q:为什么 fetch 对 404/500 不抛错?
因为 fetch 只认网络失败为错误。404/500 属于服务器正常响应,不算网络失败,必须手动判断 ok。
Q:如何取消 fetch?
使用 AbortController。
Q:GET 和 POST 到底区别是什么?
- GET:获取数据,参数在 URL,可缓存
- POST:提交数据,参数在 body,不默认缓存
新概念 + 类似概念(完整汇总)
1. HTTP 核心概念
- HTTP 请求 - 响应模型同类:客户端 / 服务端通信、请求应答模式
- HTTP 方法(GET/POST/PUT/PATCH/DELETE)同类:RESTful API、增删改查操作
- HTTP 状态码(2xx/3xx/4xx/5xx)同类:响应状态、业务状态码、接口错误码
- 请求头 / 响应头(Headers)同类:元信息、权限传递、内容类型
2. Fetch API 核心
- Fetch API同类:网络请求、AJAX、HttpClient
- Response 对象同类:响应封装、接口结果
- 请求体流(ReadableStream)同类:流式响应、分段加载、文件上传
3. 异步与控制
- AbortController同类:取消请求、中断请求、防抖
- AbortSignal同类:取消信号、中断信号
- AbortError同类:取消异常、请求终止
4. 工程模式
- 并行请求(Promise.all)同类:并发加载、批量请求
- 超时控制同类:请求超时、熔断、保护机制
- 防抖搜索同类:输入优化、避免重复请求
- 加载状态管理同类:异步状态、UI 状态、请求生命周期
5. 对比概念
- XMLHttpRequest(XHR)同类:旧式 AJAX、传统请求
- axios(同类库)同类:HTTP 客户端、请求库
- JSON 序列化同类:数据格式、字符串化

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)