跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
JavaScriptNode.js大前端

JavaScript Fetch API:如何正确克隆 Request 对象

Fetch API 支持通过构造函数或 clone 方法克隆 Request 对象。构造函数可覆盖部分属性但会将原请求体标记为已使用,clone 方法则生成完全一致的副本且不影响原对象。若请求体已被读取,任何克隆操作都会抛出错误。在 fetch 中传递带请求体的 Request 时,对象会被内部克隆并标记已使用,如需多次发送必须预先调用 clone。

leon发布于 2024/11/21更新于 2026/4/251 浏览
JavaScript Fetch API:如何正确克隆 Request 对象

Fetch API 提供了两种不太一样的方式用于创建 Request 对象的副本:使用 Request 构造函数和使用 clone() 方法。

使用 Request 构造函数克隆

将 Request 实例作为 input 参数传给 Request 构造函数,会得到该请求的一个副本:

let r1 = new Request('https://foo.com');
let r2 = new Request(r1);
console.log(r2.url); // https://foo.com/

如果再传入 init 对象,则 init 对象的值会覆盖源对象中同名的值:

let r1 = new Request('https://foo.com');
let r2 = new Request(r1, {method: 'POST'});
console.log(r1.method); // GET
console.log(r2.method); // POST

这种克隆方式并不总能得到一模一样的副本。最明显的是,第一个请求的请求体会被标记为'已使用':

let r1 = new Request('https://foo.com', {
  method: 'POST',
  body: 'foobar'
});
let r2 = new Request(r1);
console.log(r1.bodyUsed); // true
console.log(r2.bodyUsed); // false

如果源对象与创建的新对象不同源,则 referrer 属性会被清除。此外,如果源对象的 mode 为 navigate,则会被转换为 same-origin。

使用 clone() 方法克隆

第二种克隆 Request 对象的方式是使用 clone() 方法,这个方法会创建一模一样的副本,任何值都不会被覆盖。与第一种方式不同,这种方法不会将任何请求的请求体标记为'已使用':

let r1 = new Request('https://foo.com', { method: 'POST', body: 'foobar' });
let r2 = r1.clone();
console.log(r1.url); // https://foo.com/
console.log(r2.url); // https://foo.com/
console.log(r1.bodyUsed); // false
console.log(r2.bodyUsed); // false

bodyUsed 的限制

如果请求对象的 bodyUsed 属性为 true(即请求体已被读取),那么上述任何一种方式都不能用来创建这个对象的副本。在请求体被读取之后再克隆会导致抛出 TypeError。

let r = new Request('https://foo.com');
r.clone();
new Request(r);
// 没有错误
r.text(); // 设置 bodyUsed 为 true
r.clone();
// TypeError: Failed to execute 'clone' on 'Request': Request body is already used
new Request(r);
// TypeError: Failed to construct 'Request': Cannot construct a Request with a Request object that has already been used.

在 fetch() 中使用 Request 对象

fetch() 和 Request 构造函数拥有相同的函数签名并不是巧合。在调用 fetch() 时,可以传入已经创建好的 Request 实例而不是 URL。与 Request 构造函数一样,传给 fetch() 的 init 对象会覆盖传入请求对象的值:

let r = new Request('https://foo.com');
// 向 foo.com 发送 GET 请求
fetch(r);
// 向 foo.com 发送 POST 请求
fetch(r, { method: 'POST' });

fetch() 会在内部克隆传入的 Request 对象。与克隆 Request 一样,fetch() 也不能拿请求体已经用过的 Request 对象来发送请求:

let r = new Request('https://foo.com', {
  method: 'POST',
  body: 'foobar'
});
r.text();
fetch(r);
// TypeError: Cannot construct a Request with a Request object that has already been used.

关键在于,通过 fetch 使用 Request 会将请求体标记为已使用。也就是说,有请求体的 Request 只能在一次 fetch 中使用。(不包含请求体的请求不受此限制。)演示如下:

let r = new Request('https://foo.com', {
  method: 'POST',
  body: 'foobar'
});
fetch(r);
fetch(r);
// TypeError: Cannot construct a Request with a Request object that has already been used.

要想基于包含请求体的相同 Request 对象多次调用 fetch(),必须在第一次发送 fetch() 请求前调用 clone():

let r = new Request('https://foo.com', {
  method: 'POST',
  body: 'foobar'
});
// 3 个都会成功
fetch(r.clone());
fetch(r.clone());
fetch(r);

目录

  1. 使用 Request 构造函数克隆
  2. 使用 clone() 方法克隆
  3. bodyUsed 的限制
  4. 在 fetch() 中使用 Request 对象
  • 💰 8折买阿里云服务器限时8折了解详情
  • 💰 8折买阿里云服务器限时8折购买
  • 🦞 5分钟部署阿里云小龙虾了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog

更多推荐文章

查看全部
  • Java IO 流体系核心梳理:字节流与字符流详解
  • Linux 常用命令速查手册
  • 特朗普若再次执政,对人工智能行业意味着什么
  • CSS 核心机制解析:层叠、继承与优先级实战
  • RPA 技术实战指南:从原理到落地
  • 罗马数字转整数:Python 算法实现
  • SQL PASS 西雅图参会:美国签证申请实战经验
  • DeepSeek R1 颠覆提示词工程?深度解析推理模型交互变革
  • 大模型心理理论能力评估:TMBENCH 基准测试
  • 大模型内在推理能力探索:无需提示的思考链解码
  • 程序员如何规避 35 岁职业危机
  • 2024 AI 行业复盘:从百模大战到头部竞速的变革
  • 使用本地大模型从发票文本中提取结构化信息
  • 7 个鲜为人知但实用的 Python 工具库
  • Halcon 基础面试题:图像数据类型与尺寸表示
  • Flutter 返回键监听实战:双击退出与跳转桌面处理
  • Python 核心基础十分钟速览
  • Python 变量定义与标识符命名规范
  • 零基础转行 Python 工程师:我的学习路径与实战经验总结
  • 北理工 Fira:低秩约束下实现 LLM 全秩训练的新探索

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online