fetch api 的 response.body 是只读单次 readablestream,需用 getreader() 获取读取器,逐块 read() 并用 textdecoder(stream: true)解码,注意检查 body 是否存在、避免重复使用、及时释放锁。

Fetch API 返回的 Response 对象的 body 属性是一个 ReadableStream,你可以直接读取它,无需先调用 json()、text() 等封装方法。关键在于手动处理流:获取流、创建读取器、逐块读取并解码。
获取并检查响应流
发起 fetch 后,先确认响应体确实可读(response.body 存在且为 ReadableStream),再调用 getReader() 获取流读取器:
-
response.body是只读、单次消费的流,一旦被读取或丢弃,不能再重复使用 - 注意检查
response.body !== null,某些响应(如 204、304)可能没有 body - 若需多次读取,应先用
response.clone()创建副本
用 reader.read() 逐块读取 Uint8Array
流读取器的 read() 方法返回 Promise,每次解析出一个 { done, value } 对象:value 是 Uint8Array,done 为 true 表示流结束:
- 循环调用
reader.read(),直到done === true -
value是原始字节,需用TextDecoder解码为字符串(默认 UTF-8) - 避免一次性收集所有 chunk 再拼接,对大文件更省内存
完整示例:流式读取并打印文本内容
以下代码从流中实时读取、解码并输出文本,适合日志流、SSE 或大文件分块处理:
fetch('/api/stream')
.then(response => {
if (!response.body) throw new Error('Response has no body');
const reader = response.body.getReader();
const decoder = new TextDecoder();
function read() {
return reader.read().then(({ done, value }) => {
if (done) {
console.log('Stream ended');
return;
}
console.log(decoder.decode(value, { stream: true }));
return read(); // 继续读取下一块
});
}
return read();
})
.catch(err => console.error('Read error:', err));
注意:TextDecoder.decode(..., { stream: true }) 支持流式解码,能正确处理跨块的 UTF-8 多字节字符(如中文、emoji)。
常见陷阱与替代方案
直接操作 ReadableStream 灵活但易出错,需留意:
- 未调用
reader.releaseLock()可能导致后续无法读取(尤其在异常退出时) - 不加
stream: true会导致多字节字符被截断(如“你好”变成乱码) - 如只需全部内容,用
response.text()更简洁;如需结构化数据,优先用response.json() - 需要转换流(如过滤、映射),可用
TransformStream构建管道
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











