fetch api中request对象不可变但可复用,前提是不携带不可重放body(如readablestream)且未调用json()、text()等消耗方法;字符串、urlsearchparams、blob等body类型可安全多次fetch。

Fetch API 中,Request 对象本身是**不可变的**,但你可以用它来复用请求配置——关键在于:**创建一次 Request 实例,多次传给 fetch() 调用**。只要这个 Request 没被发送过(或已发送但未被 consume),它就能重复使用。
Request 对象可复用的前提条件
一个 Request 实例只有在满足以下条件时,才能被多次用于 fetch():
- 它没有携带
body(比如 GET、HEAD 请求),或者 body 是可重放的(如字符串、URLSearchParams); - 如果带 body(如 POST),且 body 是
ReadableStream(例如new Request(url, { method: 'POST', body: stream })),那它只能用一次 —— 流一旦读取就会耗尽; - 避免调用
request.json()、request.text()等 consume 方法,否则内部 body 流会被读取并锁死,后续 fetch 会失败。
安全复用 Request 的典型写法
最稳妥的方式:只用 Request 封装配置(method、headers、url),不提前消费 body,也不依赖其内部状态。
- 用字符串或
URLSearchParams作为 body,它们每次传入 fetch 都会自动重新构造流; - 把 Request 当作“配置模板”,直接传给多个
fetch(request); - 不要对它调用任何
.json()、.text()、.arrayBuffer()等方法。
示例:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
const request = new Request('/api/data', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ id: 123 })
});
// ✅ 可以多次调用
fetch(request).then(r => r.json()).then(console.log);
fetch(request).then(r => r.json()).then(console.log); // 依然成功
带 Blob/File 的请求怎么复用?
Blob 和 File 是可重放的 —— 它们每次被用作 body 时,fetch 会自动创建新的 stream。
- 直接把 Blob 放进
body字段,不用提前读取; - 确保没调用过
blob.text()或blob.arrayBuffer(),否则可能触发预读; - 这种 Request 也能安全复用。
示例:
const blob = new Blob(['{"ok":true}'], { type: 'application/json' });
const req = new Request('/upload', {
method: 'POST',
body: blob
});
fetch(req); // ✅
fetch(req); // ✅ 两次都正常发送原始 blob
哪些情况会导致复用失败?
一旦 Request 的 body 被显式消费,或底层流被读取,它就无法再次用于 fetch:
- 调用了
await request.json()或request.text(); - body 是手动创建的
ReadableStream(比如new ReadableStream({...})),且已被读取; - 在 fetch 后又尝试再次 fetch 同一 Request(仅限带不可重放 body 的情况);
- 使用了
cache: 'no-store'等不影响复用,但注意 service worker 可能拦截并修改行为。
遇到 “Failed to execute 'fetch' on 'Window': Cannot construct a Request with a used body” 错误,基本就是 body 已被 consume 过。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










