深入理解 Fetch API 的工作原理与错误处理
核心概念
Fetch API 提供了一种现代、基于 Promise 的方式来进行网络请求。它的设计遵循 分离关注点 原则,分为 获取响应 和 解析数据 两个主要阶段。
1. 基本用法
fetch(url)
.then(response => response.json()) // 解析 Response 为 JSON
.then(data => console.log(data)) // 处理解析后的数据
.catch(error => console.error(error)); // 捕获整个链的错误
fetch()
返回一个Promise
,解析为Response
对象。- 第一个
.then()
处理Response
,检查状态码(response.ok
),并调用.json()
/.text()
/.blob()
解析数据。 - 第二个
.then()
处理解析后的数据(如 JSON 对象)。 .catch()
捕获整个链中的任何错误(网络错误、HTTP 错误、解析错误等)。
2. 为什么需要两个 .then()
?
阶段 1:获取原始响应(Response)
fetch
返回的Promise
解析为Response
对象,包含 HTTP 状态、headers 等信息。- 必须手动检查
response.ok
或response.status
,因为 HTTP 错误(404、500)不会自动触发.catch()
。
阶段 2:解析数据
response.json()
/.text()
/.blob()
返回新的Promise
,因为解析可能是异步的。- 第二个
.then()
接收解析后的数据(如 JSON 对象)。
类比:拆快递
- 签收快递(第一个
.then()
):检查包裹是否完好(response.ok
)。 - 拆包裹(
.json()
):解析内容(返回新的Promise
)。 - 使用商品(第二个
.then()
):处理实际数据。
3. 错误处理机制
.catch()
捕获哪些错误?
- 网络错误(如无法连接服务器、CORS 问题)。
- HTTP 错误(需手动检查
response.ok
并throw
)。 - 解析错误(如无效 JSON)。
- 业务逻辑错误(在
.then()
中手动抛出)。
如何区分不同错误?
.catch(error => {
if (error instanceof TypeError) {
console.error("网络错误或无效 URL");
} else if (error instanceof SyntaxError) {
console.error("JSON 解析失败");
} else {
console.error("其他错误", error);
}
});
最佳实践
始终检查
response.ok
:if (!response.ok) throw new Error(`HTTP ${response.status}`);
拆分错误处理(如需精细控制):
fetch(url) .then(handleResponse) // 单独处理 HTTP 错误 .then(handleData) // 处理数据 .catch(handleNetworkError); // 捕获网络错误
4. 高级技巧
取消请求(AbortController)
const controller = new AbortController();
fetch(url, { signal: controller.signal })
.then(response => response.json())
.catch(error => {
if (error.name === 'AbortError') {
console.log("请求被取消");
}
});
// 取消请求
controller.abort();
POST 请求示例
fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ key: 'value' }),
});
总结
fetch
返回Promise<Response>
,需用.then()
处理。两个
.then()
分工明确:- 第一个处理
Response
(HTTP 层面)。 - 第二个处理解析后的数据(业务层面)。
- 第一个处理
.catch()
捕获整个链的错误,需手动检查 HTTP 错误。- 灵活运用
AbortController
、headers
和body
可满足复杂需求。