照着网上一个博客做了一个http拦截器
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { // 统一加上服务端前缀 let url = req.url; if (!url.startsWith('https://') && !url.startsWith('http://')) { url = environment.SERVER_URL + url; } const newReq = req.clone({ url }); return next.handle(newReq).pipe( mergeMap((event: any) => { // 允许统一对请求错误处理 if (event instanceof HttpResponseBase) return this.handleData(event); // 若一切都正常,则后续操作 return of(event); }), catchError((err: HttpErrorResponse) => this.handleData(err)), ); }
然后在app.module.ts里进行注册。
{ provide: HTTP_INTERCEPTORS, useClass: DefaultInterceptor, multi: true}
拦截器可以正常工作
但是我现在想在某个模块下进行自定义的错误处理
this.http.post('http://localhost:5000/api/value',data) .subscribe( (res: any) => { console.log(res) }, (error: any)=>{ console.log(error); }, ()=>{console.log("complete");} );
在服务器返回400错误的时候,这个请求上的错误处理方法就无效,但是我注释掉http拦截器,就是可以用的。
我怎么才能在有默认http拦截器的情况下,还能继续执行自定义的错误处理方案
问题出在管道 pipe 中的 catchError
catchError会拦截并处理响应中的错误,以至于后续应用程序除了响应正常的请求以外的状态都接受不到,也就无法处理错误。
解决方案:
将管道中的处理方式更换为tap来处理正常和错误响应
return next.handle(newReq).pipe( tag( event => { // 允许统一对请求错误处理 if (event instanceof HttpResponseBase) return this.handleData(event); // 若一切都正常,则后续操作 return of(event); }, error => this.handleData(error)), ) );
为什么我这里不能使用 tap函数