用 ReadableStream 流式读取 fetch 大文件需避免调用 text()/json(),改用 response.body.getReader() 逐块读取 Uint8Array,配合 TextDecoder 按需解码并处理截断字符,同时用 try/catch、reader.cancel() 和 AbortController 实现健壮的错误处理与取消机制。

用 ReadableStream 流式读取 fetch 的大文件,核心是避免把整个响应体加载进内存,而是边接收、边处理。关键在于不调用 response.text() 或 response.json() 这类“全量解析”方法,改用 response.body 获取可读流,再通过 getReader() 逐块读取。
获取并校验流式响应体
fetch 返回的 Response 对象中,body 属性就是 ReadableStream(前提是服务器支持分块传输且未禁用流)。需先确认请求成功且响应体存在:
- 检查
response.ok和response.status确保 HTTP 状态正常 - 确认
response.body不为null(某些重定向或空响应可能没有 body) - 可选:用
response.headers.get('content-length')预估大小(但流式场景下该值常为空,因分块传输不预设总长)
用 reader 循环读取 chunk
调用 response.body.getReader() 获取 ReadableStreamDefaultReader,然后用 read() 方法持续拉取数据块:
-
read()返回 Promise,resolve 结果为{ done: boolean, value: Uint8Array } -
value是Uint8Array,即原始二进制数据块,可直接处理(如解码为字符串、写入文件、解析 CSV 行等) -
done === true表示流已结束,循环应终止 - 建议用
while+await或递归read(),避免阻塞主线程
按需解码或转换数据块
流式读取的是二进制,若需文本处理(如日志、JSON Lines、CSV),需手动解码:
- 用
new TextDecoder('utf-8').decode(chunk)将Uint8Array转为字符串 - 注意:单个 chunk 可能截断多字节字符(如 UTF-8 中文),建议缓存未完整字符,拼接到下一块再解码
- 对结构化格式(如每行一个 JSON),可在解码后按换行符
\n分割,并逐行JSON.parse()—— 无需等待全部下载完成
错误处理与取消机制
网络流不稳定,必须捕获异常并支持主动中断:
- 在
read()的 Promise 上用.catch()处理网络中断、解码失败等错误 - 调用
reader.cancel()可主动终止读取(例如用户点击取消按钮) - 使用
AbortController控制 fetch 请求本身:fetch(url, { signal }),取消 signal 即中断整个请求和流

















