Angular HttpClient开启进度上报后如何同时监听进度并返回指定类型Observable
解决方案
核心思路是通过RxJS操作符在流内部处理进度监听逻辑,最后将流转换回原有ApiResponseInterface类型即可,对外暴露的接口完全不变,不影响上层业务代码的调用。
完整实现代码
首先导入所需依赖:
import { Observable } from 'rxjs'; import { tap, filter, map } from 'rxjs/operators'; import { HttpClient, HttpEvent, HttpEventType, HttpResponse } from '@angular/common/http'; // 替换为你实际的ApiResponseInterface导入路径 import { ApiResponseInterface } from './interface/xxx';
改造后的post方法:
post(url: string, body?: any): Observable<ApiResponseInterface> { return this.httpClient.post<ApiResponseInterface>(url, body, { // 开启进度上报、监听全量事件 reportProgress: true, observe: 'events' }).pipe( // 不改变流内容,仅在内部处理进度事件 tap((event: HttpEvent<ApiResponseInterface>) => { // 处理上传进度 if (event.type === HttpEventType.UploadProgress) { const progress = Math.round(100 * event.loaded / (event.total || 1)); // 这里替换为你自己的进度条更新逻辑 console.log(`上传进度:${progress}%`); } // 处理下载进度,不需要可以删掉 if (event.type === HttpEventType.DownloadProgress) { const progress = Math.round(100 * event.loaded / (event.total || 1)); console.log(`下载进度:${progress}%`); } }), // 过滤掉进度事件,仅保留请求完成后的响应事件 filter((event: HttpEvent<ApiResponseInterface>) => event.type === HttpEventType.Response), // 提取响应体,转换为你需要的ApiResponseInterface类型 map((event: HttpResponse<ApiResponseInterface>) => event.body as ApiResponseInterface) ); }
方案优势
- 对外接口完全兼容:返回类型仍为
Observable<ApiResponseInterface>,原有业务侧调用代码不需要做任何修改 - 逻辑解耦:进度上报逻辑封装在请求方法内部,和业务逻辑互不干扰
- 类型安全:全程符合TypeScript类型校验,没有类型丢失问题
- 错误处理逻辑不受影响:请求产生的异常会正常向下传递,原有订阅的错误回调逻辑可以正常使用
内容的提问来源于stack exchange,提问作者MMMWeirdo
相关产品推荐
相关产品推荐

