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

如何访问Promise响应体的ReadableStream及设置MP3缓存类型

解决MP3缓存与播放的两个问题

一、强制缓存MP3为audio/mp3类型

cache.add()会直接沿用服务器返回的响应头,若服务器返回的是audio/mpeg,缓存里的类型也会同步这个值。要强制改成audio/mp3,需要手动获取响应、修改头信息后再存入缓存:

const request = URL_TO_MY_MP3_FILE;
caches.open("my-cache").then(async cache => {
  // 先获取原始响应
  const originalResponse = await fetch(request);
  // 克隆响应并修改Content-Type
  const modifiedResponse = new Response(originalResponse.body, {
    headers: new Headers(originalResponse.headers),
    status: originalResponse.status,
    statusText: originalResponse.statusText
  });
  modifiedResponse.headers.set('Content-Type', 'audio/mp3');
  // 替换缓存中的响应
  await cache.put(request, modifiedResponse);
});

重新执行后,在Application标签中查看缓存的响应头,Content-Type就会显示为audio/mp3。

二、修复缓存读取时response.body未定义及播放问题

你遇到的问题有两个核心原因:

  1. cache.match()返回的是Promise,不能直接同步获取response对象;
  2. Audio构造函数不支持直接传入ReadableStream,需要将响应转为Blob后生成可访问的URL。

修正后的代码:

const request = URL_TO_MY_MP3_FILE;
caches.open("my-cache").then(async cache => {
  // 等待Promise获取响应
  const response = await cache.match(request);
  if (!response) {
    console.error("目标MP3不在缓存中");
    return;
  }
  // 将响应转为Blob对象
  const audioBlob = await response.blob();
  // 创建Blob的可访问本地URL
  const audioObjectUrl = URL.createObjectURL(audioBlob);
  // 初始化Audio实例
  this.audio = new Audio(audioObjectUrl);
  
  // 音频播放结束后释放URL,避免内存泄漏
  this.audio.addEventListener('ended', () => {
    URL.revokeObjectURL(audioObjectUrl);
  });
  
  // 按需触发播放
  // this.audio.play();
});

关键说明:

  • 必须用await或.then()处理cache.match()的Promise,才能拿到有效的响应对象;
  • response.blob()会将响应体转为Blob格式,再通过URL.createObjectURL()生成Audio可识别的本地URL;
  • 音频使用完毕后调用URL.revokeObjectURL()释放资源,防止不必要的内存占用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 03:24:20