Angular HTTP拦截器未转发reportProgress事件至组件的问题
解决Angular拦截器无法转发上传进度事件的问题
我一眼就发现问题出在你的LoaderInterceptor里——你现在只把HttpResponse类型的事件转发给了组件的观察者,而上传进度相关的HttpProgressEvent(比如上传开始、进度更新这类事件)全被拦截器“吞”掉了,所以组件那边自然收不到进度信息。
问题根源
在你的拦截器代码中,只有当event instanceof HttpResponse时才调用observer.next(event),但上传过程中的进度事件属于其他HttpEvent子类,根本没被转发出去。你在拦截器里能看到console.log(event)输出进度事件,但组件的订阅接不到,就是因为这一步的遗漏。
修复拦截器代码
修改LoaderInterceptor的subscribe回调,把所有事件都转发给观察者,然后在合适的时机(收到响应、错误、完成时)处理请求队列的清理:
import {Injectable} from '@angular/core'; import { HttpResponse, HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HttpEventType } from '@angular/common/http'; import {Observable} from 'rxjs'; import {StateService} from '../services/state.service'; @Injectable() export class LoaderInterceptor implements HttpInterceptor { private requests: HttpRequest<any>[] = []; constructor(private alertService: AlertService, private stateService: StateService) { } removeRequest(req: HttpRequest<any>) { const i = this.requests.indexOf(req); if (i >= 0) { this.requests.splice(i, 1); } this.stateService.isLoading$.next(this.requests.length > 0); } intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { this.requests.push(req); this.stateService.isLoading$.next(true); return new Observable(observer => { const subscription = next.handle(req) .subscribe( event => { console.log(event); // 转发所有事件,包括进度事件! observer.next(event); // 只有当是响应事件时才清理请求 if (event instanceof HttpResponse) { this.removeRequest(req); } }, err => { this.alertService.setAlert('error', err.message); this.removeRequest(req); observer.error(err); }, () => { this.removeRequest(req); observer.complete(); }); return () => { this.removeRequest(req); subscription.unsubscribe(); }; }); } }
为什么这样改?
- 移除了对
HttpResponse的判断,直接把所有HttpEvent(包括进度事件、响应事件等)都通过observer.next(event)转发给组件的订阅。 - 只在收到
HttpResponse、错误或者流完成时清理请求队列,保证加载状态的逻辑不受影响。
组件端优化(可选)
你的upload.component.ts基础配置已经没问题了,要是想更清晰地处理进度,可以在订阅时判断事件类型:
this.http.request(req) .pipe( tap(event => { if (event.type === HttpEventType.UploadProgress) { // 计算上传进度百分比 const progress = Math.round(100 * event.loaded / (event.total || 1)); console.log(`${file.name} 上传进度: ${progress}%`); } else if (event instanceof HttpResponse) { console.log(`${file.name} 上传完成`); } }) ) .subscribe();
内容的提问来源于stack exchange,提问作者MFB
相关产品推荐
相关产品推荐

