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

