【JavaScript】了解为什么Fetch有时候需要两次 await
|
admin
2024年12月28日 23:21
本文热度 31
|
在 JavaScript 中,fetch
API 是一种常见的 HTTP 请求工具,但其需要两次 await
的机制可能让初学者感到疑惑。本文将通过示例与解析,理解这一特性。
基础示例
const response = await fetch('https://api.example.com/data');
const data = await response.json();
上面的代码为什么需要两次 await
?
Fetch 的两阶段流程
1. 获取响应
调用 fetch
时,它返回一个 Promise,在网络请求完成后解析为 Response 对象:
- 仅获取元数据:此时只获取响应头信息,正文尚未处理。
2. 解析响应正文 📄
Response 对象包含的方法(如 .json()
、.text()
)用于读取正文,这些方法返回另一个 Promise,因为读取和解析正文是异步操作。
第一次 await
的内部流程
当你执行以下代码:
const response = await fetch(url);
1. 发送请求
浏览器向指定 URL 发起网络请求:
2. 接收响应元数据
- 服务器返回状态行(如
HTTP/1.1 200 OK
)和响应头后,fetch
的 Promise 解析。 - 响应头:如
Content-Type: application/json
3. 构造 Response 对象
- Headers:通过
response.headers
获取。
第二次 await
的内部流程
当你执行以下代码:
const data = await response.json();
1. 读取正文流
Response 对象的正文被解析为流:
.json()
:解析为 JSON 并返回 JavaScript 对象。
2. 异步解析
- 流数据被解析为可用内容(如
{ message: "Hello, world!" }
)。
3. 返回解析结果
response.json()
返回的 Promise 解析为解析后的数据,可用于程序逻辑。
为什么需要两次 await
?
两次 await
是 Fetch 的设计逻辑,分别解决以下问题:
- 等待网络请求完成,获取 Response 对象(包含状态码、头信息等元数据)。
如果跳过任意一次 await
会如何?
- 你将得到一个未解析的 Promise,而非 Response 对象。
- 你将得到未解析的 Promise,而非解析后的数据。
完整示例:带错误处理
以下是一个完整的示例,展示如何正确处理错误:
try {
const response = await fetch('https://api.example.com/data');
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error fetching data:', error);
}
错误处理注意点:
- **检查
response.ok
**:fetch
不会对 HTTP 错误(如 404 或 500)抛出异常。 - 捕获解析错误:如果响应正文不符合预期格式(如 JSON 格式错误),解析时也会抛出异常。
常见问题与解决方案
1. 忘记错误处理
- 问题:
fetch
默认不会对 HTTP 错误抛出异常,可能导致你误以为请求成功。 - 解决:手动检查
response.ok
或 response.status
。
2. 忘记第二次 await
- 问题:会导致代码处理未解析的 Promise,而非实际数据。
- 解决:始终
await
解析方法(如 .json()
)。
3. 旧 API 的影响
- 问题:从
XMLHttpRequest
等同步 API 迁移的开发者可能预期同步行为。 - 解决:理解并适应
fetch
的 Promise 异步设计。
总结
使用 Fetch API 时,两次 await
是其异步设计的结果:
- **第一次
await
**:确保接收到响应元数据。 - **第二次
await
**:解析响应正文,获取最终数据。
理解 Fetch 的工作机制能帮助你编写更高效、可靠的异步代码!
阅读原文:原文链接
该文章在 2024/12/30 14:37:42 编辑过