如何访问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未定义及播放问题
你遇到的问题有两个核心原因:
cache.match()返回的是Promise,不能直接同步获取response对象;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
相关产品推荐
相关产品推荐

