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

Angular中Observable返回Blob时localStorage分支subscribe取不到值问题

问题根因

localStorage分支的自定义Observable写法不符合RxJS规则:自定义Observable的回调入参是观察者对象,必须主动调用observer.next()推送值才能触发subscribe的回调,直接return返回值不会被订阅者接收,这就是console.log没有输出的核心原因。

修复代码

服务层修正

直接用RxJS内置的of()操作符返回同步值,比手动new Observable更简洁规范:

// 顶部先导入of操作符
import { of } from 'rxjs';

getAudioFile (text: string): Observable<Blob> {
  const cachedContent = localStorage.getItem(text);
  if (cachedContent) {
    // of会自动把值推送给订阅者,触发subscribe回调
    return of(new Blob([cachedContent], {type: 'audio/wav'}));
  }
  return this.http.post(this.cors + this.apiUrl, {}, {
      headers: {
        'Content-Type' : 'application/json',
        'Accept' : 'audio/wav',
      },
      params: {
        voice: 'en-US_AllisonV3Voice',
        text : text
      },
      responseType: 'blob'
    }).pipe(map(res => {
      res.text().then((strBlob => {
        localStorage.setItem(text, strBlob);
      }))
      return res;
   }),catchError(this.handleError))
}

如果你坚持要手动构造Observable,正确写法如下:

return new Observable(observer => {
  // 推送Blob值给订阅者
  observer.next(new Blob([cachedContent], {type: 'audio/wav'}));
  // 标记流结束
  observer.complete();
})

可选优化建议

当前直接把Blob转普通字符串存入localStorage的方案,在部分字符编码场景下可能出现音频解码失败的问题,建议改为Base64格式存储:

// API返回时存Base64
res => {
  const reader = new FileReader();
  reader.readAsDataURL(res);
  reader.onloadend = () => {
    localStorage.setItem(text, reader.result as string);
  }
  return res;
}

// 从localStorage读取时转Blob
if (cachedContent) {
  return of(fetch(cachedContent).then(res => res.blob()));
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 08:12:02