await fetch() 的两阶段设计
结论
await fetch() 只等待响应头(Headers)返回,不包含完整的响应体(Body)。
设计原理
Fetch API 采用两阶段设计,以提升效率和灵活性:
第一阶段:等待响应头
执行 await fetch(url) 时,JavaScript 会暂停,直到服务器返回 HTTP 状态码和响应头。此时 Promise 变为 fulfilled,你得到一个 Response 对象,其中包含:
status(如 200)okheaders
但响应体的数据流可能还在传输中。
第二阶段:等待响应体
获取 Response 对象后,需要显式调用 response.json()、response.text() 或 response.blob() 等方法来读取响应体。这些方法本身也返回一个 Promise,需要第二个 await 来等待数据流读取和解析完成。
代码示例
javascript
async function getData() {
try {
// 第一个 await:等待响应头,获取 Response 对象
const response = await fetch('https://api.example.com/data');
// 此时可以立即检查响应状态
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
// 第二个 await:等待响应体被完全读取和解析
const data = await response.json();
console.log('数据获取成功:', data);
} catch (error) {
console.error('请求失败:', error);
}
}
这种设计的两大好处
-
快速错误处理:在下载可能很大的响应体之前,就能根据状态码(如 404 或 500)快速判断请求是否成功,节省带宽和时间。
-
流式处理 :对于大文件,可以不一次性加载到内存,而是通过
response.body.getReader()分块读取和处理数据流,有效避免内存溢出。