正在加载...

Fetch API

fetch(url) 会让浏览器发送 HTTP 请求,并立即返回 Promise。该 Promise 通常兑现为 Response,而不是已经解析的 JSON。

先取得 Response,再取得数据

await fetch(...) 得到状态码、响应头和正文流。response.json() 读取正文文本、按 JSON 解析,并返回另一个以 JavaScript 数据兑现的 Promise。

两个独立阶段

请把传输响应和解析正文分开理解。响应可以有重要状态码,但正文未必是 JSON。

📊 从请求到数据

表达式 结果 含义
fetch(url) Promise<Response> 请求已开始
await fetch(url) Response 状态、响应头和正文流
response.json() Promise<any> 读取并解析正文
await response.json() JavaScript 数据 解析后的对象或值

fetch 返回 Promise

这个独立示例只用 Blob URL 展示返回类型。Blob URL 是浏览器内存资源,并非同源 HTTP endpoint。

fetch 返回 Promise

javascript
const blob = new Blob(['{"drink":"lida tea"}'], { type: "application/json" });
const url = URL.createObjectURL(blob);
const ticket = fetch(url);
console.log(ticket instanceof Promise);
ticket.finally(() => URL.revokeObjectURL(url));

输出为 true。实际项目中可把 Blob URL 换成 /data/drink.json 等 HTTP 路径。

先等待 Response,再等待 JSON

下一个示例创建相同的本地资源,并完成两次等待。

等待 Response 和 JSON

javascript
async function loadDrink() {
const blob = new Blob(['{"drink":"lida tea"}'], { type: "application/json" });
const url = URL.createObjectURL(blob);
try {
const response = await fetch(url);
if (!response.ok) throw new Error("HTTP " + response.status);
const data = await response.json();
console.log(data.drink);
} finally {
URL.revokeObjectURL(url);
}
}
loadDrink();

输出为 lida tea。真实的 /data/drink.json 可以包含 {"drink":"lida tea"},读取步骤完全相同。

明确检查 HTTP 错误

即使服务器返回 404 或 500,fetch 通常仍会兑现。网络故障可能导致拒绝,但失败状态码本身通常不会。应检查 response.ok 或 response.status。

检查 HTTP 错误响应

javascript
const response = new Response("Not found", {
status: 404,
statusText: "Not Found"
});
console.log(response.ok);
console.log(response.status);

构造的响应依次输出 false 和 404,这正是真实 fetch 后要检查的属性。除非 API 明确保证,否则不要把错误页面当 JSON 解析。

json 也返回 Promise

json() 会异步读取并解析正文。

json 返回 Promise

javascript
const response = new Response('{"drink":"lida tea"}', {
headers: { "Content-Type": "application/json" }
});
const dataPromise = response.json();
console.log(dataPromise instanceof Promise);
dataPromise.then(data => console.log(data.drink));

输出为 true。执行 await response.json() 后,data 是 JavaScript 对象,data.drink 是字符串。

不依赖 endpoint 的页面示例

示例 fetch 一个 Blob URL,因此可独立运行。它展示流程和状态 200,但不会把它说成服务器请求。

独立 fetch 页面

html
<!DOCTYPE html>
<html>
<body>
<p id="cup">blank</p>
<p id="line">…</p>
<script>
async function load() {
const blob = new Blob(['{"drink":"lida tea"}'], { type: "application/json" });
const url = URL.createObjectURL(blob);
try {
const response = await fetch(url);
if (!response.ok) throw new Error("HTTP " + response.status);
const data = await response.json();
document.getElementById("cup").textContent = data.drink;
document.getElementById("line").textContent =
response.status + " / " + data.drink;
} finally {
URL.revokeObjectURL(url);
}
}
load();
</script>
</body>
</html>

页面显示 200 / lida tea。生产环境应使用 HTTP URL,并在解析前继续检查 ok。

动手试试

在本地服务器创建 /data/drink.json 并替换 Blob URL,再请求不存在的路径,对比 ok 与 status。

常见错误

不要把 fetch 返回的 Promise 当成数据。不要忘记调用并等待 json()。也不要只靠 catch 判断每个 404。

小结

fetch 发送请求,并给出以 Response 兑现的 Promise。先检查 ok,再解析预期正文。response.json() 返回 JavaScript 数据的 Promise。

🧠 测试您的知识

准备开始

测试您的知识

通过这个互动测验挑战自己,看看你对这个主题的理解程度如何

❓
5
问题
🎯
70%
及格要求
♾️
∞
时间
🔄
∞
尝试次数

📝 说明

  • 仔细阅读每个问题
  • 为每个问题选择最佳答案
  • 您可以随时重新参加测验
  • 您的进度将显示在顶部