You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Service Worker请求失败时返回请求对象作为响应仅获空内容问题咨询

问题分析与解决方案

这种需求完全是可行的,但你遇到的问题根源在于Request对象是一个复杂的DOM API实例,它的大部分属性并不是可枚举的自有属性——JSON.stringify()只会序列化对象中可枚举的自有属性,所以直接展开event.request的时候,除了你自己加的deferred: true,其他属性都被忽略了,这就是为什么响应里只有那一个键值对。

至于你用了.clone(),它只是复制了Request对象本身,让你可以重复使用它的body内容,但并不能改变它的序列化行为,所以解决不了这个问题。

正确的实现方式

要把请求的信息序列化到响应里,你需要手动提取Request对象的关键属性,把它们转换成普通的JavaScript对象后再进行JSON序列化。这里给你一个示例:

fetch(event.request.clone())
  .catch(async (err) => {
    queue.addRequest(event.request);
    
    // 手动提取请求的核心信息
    const requestInfo = {
      deferred: true,
      url: event.request.url,
      method: event.request.method,
      // 把Headers对象转换成普通键值对对象
      headers: Object.fromEntries(event.request.headers.entries()),
      // 如果需要包含请求体,要先读取(注意必须用clone后的请求,避免消耗原请求的body)
      body: await event.request.clone().text(),
      // 可以根据需求添加更多属性,比如请求模式、凭证设置等
      mode: event.request.mode,
      credentials: event.request.credentials
    };

    return new Response(JSON.stringify(requestInfo), {
      headers: new Headers({ "Content-Type": "application/json" })
    });
  });

注意事项

  • 如果你的请求体是二进制数据(比如文件上传),不要用.text()读取,改用.arrayBuffer()后转换成Base64字符串,这样才能被JSON序列化。
  • 每次读取请求体的时候必须用clone()后的Request实例,因为原Request的body只能被消费一次——如果你的queue.addRequest()之后还需要重新发送这个请求,必须保证原请求的body没有被提前消耗掉。
  • 不是所有Request的属性都需要提取,你可以根据自己的需求选择需要的字段(比如只保留url、method和headers)。

内容的提问来源于stack exchange,提问作者Victor Castro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:36:33