fetch 支持流式读取响应体,需通过 response.body 获取 readablestream,调用 getreader() 创建读取器,循环调用 read() 获取 uint8array 分块,用 textdecoder 解码并处理(如按行分割),注意检查 body 是否存在、捕获错误、主动取消及 releaselock。

Fetch 支持流式读取响应体,关键在于使用 response.body 获取可读流(ReadableStream),再通过 getReader() 创建流读取器,配合 reader.read() 循环读取分块数据。整个过程需手动处理 Uint8Array、解码、中断逻辑和错误恢复。
获取流并创建读取器
发起 fetch 请求后,不调用 response.text() 或 response.json() 等终结方法,而是直接访问 response.body:
-
response.body是一个ReadableStream实例(仅当响应头允许流式传输时存在,如Content-Type: text/event-stream或普通 HTTP 响应) - 必须检查
response.body是否存在,某些场景(如 CORS 错误或重定向)可能导致其为null - 调用
response.body.getReader()获取ReadableStreamDefaultReader,它支持逐块拉取二进制数据
循环读取并解码分块数据
使用 reader.read() 返回的 Promise 解构 { done, value },其中 value 是 Uint8Array:
-
value每次为一个数据块(大小由底层网络和浏览器决定,通常几 KB 到几十 KB) - 用
new TextDecoder().decode(chunk)将Uint8Array转为字符串(推荐复用TextDecoder实例避免重复创建) - 若需按行/按消息解析(如 SSE 或自定义协议),可在解码后用
split('\n')或正则提取完整单元,缓存未结束的片段 -
done === true表示流已关闭,循环结束
处理错误与提前终止
流读取过程中可能因网络中断、服务器关闭或主动取消而失败:
- 在
reader.read()的 Promise catch 中捕获异常,如TypeError: Failed to fetch或AbortError - 调用
reader.cancel('reason')可主动中止读取(例如用户点击“停止”按钮) - 用
AbortController控制整个 fetch 请求生命周期,controller.abort()会同时中断请求和后续读取 - 注意:
reader.releaseLock()在不再读取时调用,否则无法再次调用getReader()
实用代码片段
以下是一个最小可行示例,带基础错误处理和文本解码:
const controller = new AbortController();
const response = await fetch('/stream-endpoint', { signal: controller.signal });
if (!response.body) throw new Error('Response has no body');
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
// 示例:按行处理(适合日志、SSE)
const lines = buffer.split('\n');
buffer = lines.pop() || ''; // 保留不完整的最后一行
for (const line of lines) {
if (line.trim()) console.log('Received:', line);
}
}
// 处理缓冲区中剩余内容
if (buffer.trim()) console.log('Remaining:', buffer);
} catch (err) {
if (err.name === 'AbortError') {
console.log('Fetch aborted');
} else {
console.error('Stream error:', err);
}
} finally {
reader.releaseLock();
}
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











