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

Angular 5拦截器疑问:如何仅在请求完成时执行操作?

解决Angular 5拦截器中加载条无法正常显示的问题

嘿,我完全get到你的问题了!你现在的问题根源出在对map操作符的使用上,还有Angular HTTP请求Observable的事件机制——听我给你拆解清楚:

为什么原来的代码会失效?

next.handle(req)返回的Observable并不是只在请求成功时发出一个值,它会发出一系列HTTP事件:比如请求发送出去时的HttpSentEvent、上传进度的HttpProgressEvent,最后才是成功响应的HttpResponse。而map操作符会对每一个发出的事件都执行回调,所以当请求刚发送出去(第一个事件触发),你的map就把loading设为false了,加载条自然刚显示就消失,根本等不到请求完成。

而你测试长耗时500错误时,删除map后加载条正常,是因为此时只有catch会在错误发生时触发重置loading,中间没有其他事件提前把状态改掉。

正确的解决方案:使用finalize操作符

RxJS的finalize操作符就是专门用来处理这种“无论Observable正常完成还是出错终止,都要执行的收尾操作”的,它只会在整个Observable生命周期结束时执行一次,完美匹配你“请求完成时执行操作”的需求。

修改后的拦截器代码如下:

// 先导入finalize操作符(Angular 5基于RxJS 5,需要这样导入)
import 'rxjs/add/operator/finalize';

// ...

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    console.log('Creating HTTP request');
    this.session.loading = true;
    
    return next
        .handle(req)
        .finalize(() => {
            this.session.loading = false;
            console.log('Ending HTTP request');
        });
}

为什么这个方案可行?

  • finalize的回调只会在请求完全结束时触发:不管是成功收到响应,还是请求失败抛出错误,它都会执行一次
  • 不用再在map和catch里重复写相同的重置代码,代码更简洁易维护
  • 不会被中间的HTTP事件(比如发送事件、进度事件)提前触发,确保加载条从请求开始显示到请求结束才隐藏

这样修改后,你的加载条就能正常工作啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:57:39