Fetch API 中复用请求配置的核心是通过 Request 构造函数结合 clone() 与新构造实现动态覆盖,或封装工厂函数统一管理 headers、credentials 等公共选项,并注意 Request 实例不可变性。

在 Fetch API 中,通过 Request 构造函数复用请求配置的核心思路是:**把公共的请求选项(如 headers、method、credentials)预先封装成一个 Request 实例或配置对象,再结合不同 URL 或 body 动态生成新请求**。直接复用 Request 实例本身受限(因为 Request 是不可变的),但可以基于它派生新请求。
用 Request 实例作为模板,用 clone() + new Request() 构造新请求
Request 实例不可修改,但支持 clone() 方法复制一份,并允许在构造新 Request 时覆盖部分字段(如 url、body)。这是最贴近“复用配置”的方式:
- 先创建一个基础
Request模板(含 headers、credentials 等) - 调用
template.clone()获取副本 - 用
new Request(url, { ...options })覆盖所需字段(注意:不能直接改 clone 后的实例,需传入新配置)
示例:
// 基础配置模板(不含具体 URL 和 body)
const baseRequest = new Request('/api/', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer token123' },
credentials: 'include'
});
// 复用模板发请求 A
fetch(new Request('/api/users', { ...baseRequest, body: JSON.stringify({ name: 'Alice' }) }))
// 复用模板发请求 B(仅改 URL 和 body)
fetch(new Request('/api/posts', { ...baseRequest, body: JSON.stringify({ title: 'Hello' }) }))
更推荐:封装成可复用的工厂函数
比直接操作 Request 更清晰、灵活。把固定配置提取为函数参数或闭包变量,动态注入 URL 和 payload:
立即学习“Java免费学习笔记(深入)”;
- 避免重复写 headers/credentials 等 boilerplate
- 便于统一处理认证 token 刷新、日志、错误格式化等逻辑
- 天然支持 TypeScript 类型推导和 IDE 提示
示例:
const createApiRequest = (url, options = {}) =>
new Request(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${localStorage.getItem('token') || ''}`
},
credentials: 'include',
...options
});
// 使用
fetch(createApiRequest('/api/login', { body: JSON.stringify({ u: 'a', p: 'b' }) }))
fetch(createApiRequest('/api/profile', { method: 'GET', body: null }))
注意 Request 实例的不可变性与常见误区
Request 对象一旦创建,其 url、method、headers 等属性是只读的。试图直接赋值会静默失败:
-
req.url = '/new'不生效(仍为原 URL) -
req.headers.set('X-Trace', '1')报错(Headers 对象不可写) -
req.clone()返回新实例,但仍是只读 —— 必须用new Request(...)才能真正“定制”
因此,“复用”本质是复用配置对象,而非复用实例本身的状态。
配合 AbortController 实现可取消的复用请求
若需为多个复用请求统一控制中止,可在工厂函数中注入 signal:
- 创建一个
AbortController实例 - 所有请求都传入
signal: controller.signal - 调用
controller.abort()即可批量取消
示例:
const controller = new AbortController();
const reqA = new Request('/api/data', {
signal: controller.signal,
// ...其他复用配置
});
const reqB = new Request('/api/status', {
signal: controller.signal,
// ...相同 headers/credentials
});
// 发起请求
fetch(reqA); fetch(reqB);
// 任意时刻取消全部
// controller.abort();


















