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
相关产品推荐
相关产品推荐

