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

