需调用response.body.getReader()获取reader,再用while循环或for await...of反复调用read()逐块读取Uint8Array,配合TextDecoder({stream: true})解码,避免text()/json()全量加载。

fetch 返回的 ReadableStream 怎么分块读取
Fetch 的 response.body 是一个 ReadableStream,但它默认不自动分块;你得手动调用 getReader(),再循环 reader.read() 才能拿到 chunks。直接 response.text() 或 response.json() 会把整个响应体读完再返回,失去流式意义。
常见错误是以为 await response.body.getReader().read() 一次就能拿到全部数据——其实它只返回一个 { done: false, value: Uint8Array },value 是当前 chunk,必须反复调用直到 done === true。
- 必须用
while循环或递归处理reader.read(),不能只 await 一次 -
value是Uint8Array,不是字符串,需用new TextDecoder().decode(chunk)转换 - 如果服务端没设置
Transfer-Encoding: chunked或没持续 flush 输出,浏览器可能长时间卡在第一个read()
如何避免阻塞主线程并实时处理每个 chunk
直接在主线程里 while 循环 await reader.read() 会导致界面卡顿(尤其大 chunk 或慢响应)。正确做法是用 async iterator 语法配合 for await...of,它底层自动处理微任务调度,比手写 while 更轻量、不易出错。
但注意:for await...of 只适用于支持 async iteration 的 stream(现代浏览器都支持),且不能中途 abort —— 如果需要中断,必须显式调用 reader.cancel() 并 catch AbortError。
- 推荐写法:
for await (const chunk of reader) { ... },chunk 就是Uint8Array - 若需 AbortController 控制,初始化 reader 后立刻监听
signal.aborted,并在循环中检查 - 不要在 decode 后直接拼接长字符串(如
str += decoded),频繁内存分配影响性能;可先收集Uint8Array再批量 decode
遇到 RangeError: Invalid array buffer length 怎么办
这个错误通常发生在服务端返回空 chunk(value.length === 0)后,你还试图用 TextDecoder.decode() 处理它——某些老版本 Chrome 对零长 buffer 解码会抛 RangeError。
根本原因是没过滤空 chunk,或误把 done === true 后的 value(为 undefined)传给 decode。
- 安全解码写法:
if (chunk && chunk.length > 0) { decoder.decode(chunk, { stream: true }) } - 务必加
stream: true参数,否则多字节字符(如 emoji、中文)跨 chunk 时会乱码 - 服务端若返回
Content-Length: 0但仍有 body 流,也可能触发该错,此时应检查响应头是否矛盾
为什么用 TextDecoder 比直接 new Blob([...chunks]).text() 更合适
Blob.text() 是一次性异步操作,它会等整个 stream 结束才 resolve,完全违背流式初衷;而 TextDecoder 支持流式解码(靠 stream: true),能边收边转,延迟更低。
另外,Blob 构造函数要拷贝所有 Uint8Array,内存占用随数据增长线性上升;TextDecoder 只维护内部状态,更省内存。
- 流式场景下,
TextDecoder是唯一合理选择 - 别用
response.arrayBuffer()或response.blob(),它们消耗完整响应体 - 如果后端返回 JSON 分块(如 NDJSON),记得按换行切分
decoder.decode(chunk)结果,再逐行 parse
实际中最容易被忽略的是 TextDecoder 的 stream: true 参数——漏掉它,中文一断就乱码,而且问题不会立刻暴露,要等特定字符出现在 chunk 边界才会浮现。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











