fetch api 本身不提供“预解压”功能,因为 http 协议中的 content-encoding(如 gzip、br)由浏览器网络栈自动处理,开发者无法在 javascript 层拦截并手动解压原始压缩流。要实现类似效果,必须依赖后端服务直接返回未压缩数据,或者使用 service worker 等中间件拦截响应进行转换。

如何强制后端返回未压缩数据
最直接的做法是修改请求头,通过设置 Accept-Encoding: identity 告诉服务器不要对响应体进行压缩。这样服务器会返回原始的 JSON 或文本数据,JavaScript 接收到的就是已经“解压”好的明文,无需任何额外处理。

fetch('https://api.example.com/data', {
headers: {
'Accept-Encoding': 'identity'
}
})
.then(response => response.json())
.then(data => console.log(data));
上述代码中,Accept-Encoding: identity 是关键参数。如果服务器支持该指令,它将跳过 gzip 或 brotli 压缩步骤,直接发送原始字节流。此时 response.body 包含的是未压缩的数据,response.json() 可以直接解析,不存在解码延迟或 CPU 开销。需要注意的是,并非所有服务器都严格遵循此头部,部分 CDN 或反向代理可能会忽略它,因此需在实际环境中验证响应头的 Content-Encoding 是否为空。
立即学习“Java免费学习笔记(深入)”;
如何在 Service Worker 中拦截并解压
当无法控制后端时,可以在 Service Worker 中拦截 Fetch 事件,读取压缩后的响应体,利用浏览器内置的 DecompressionStream API 进行实时解压,再返回未压缩的响应。这种方法实现了客户端的“预解压”,让后续业务逻辑直接处理明文数据。

// service-worker.js
self.addEventListener('fetch', event => {
if (event.request.url.includes('/api/data')) {
event.respondWith(
fetch(event.request)
.then(async response => {
const originalResponse = response.clone();
const contentEncoding = response.headers.get('Content-Encoding');
if (contentEncoding === 'gzip' || contentEncoding === 'br') {
const decompressedStream = new DecompressionStream(contentEncoding);
const transformedStream = response.body.pipeThrough(decompressedStream);
return new Response(transformedStream, {
status: response.status,
statusText: response.statusText,
headers: new Headers(originalResponse.headers)
});
}
return response;
})
);
}
});
这段代码展示了在 Service Worker 中使用 DecompressionStream 的过程。首先克隆原始响应以保留头部信息,然后检查 Content-Encoding 头部。如果检测到 gzip 或 br,则创建对应的 DecompressionStream 实例,并通过 pipeThrough 将原始压缩流转换为未压缩流。最终构造一个新的 Response 对象返回给主线程。这种方式下,主线程获取到的 response.body 已经是解压后的数据,可以直接调用 json() 或 text(),且整个过程是异步流式处理的,不会阻塞 UI。
DecompressionStream 在不同编码下的行为差异
在使用 DecompressionStream 时,传入的编码字符串必须与响应头中的 Content-Encoding 完全一致,否则会导致解压失败或抛出异常。例如,对于 gzip 编码,必须传入 'gzip';对于 brotli 编码,必须传入 'br'。如果传入错误的编码或不支持的编码,pipeThrough 操作会立即失败,导致整个 Fetch 请求中断。


















