某些情况下存在因为特殊原因导致短时间的请求失败,这时可以在 pipe 管道中,当请求失败后,使用 retry 方法进行多次的请求重试,在进行了多次重试后还是无法进行数据通信后,则进行错误捕获
getAntiMotivationalQuotes(): Observable<GetQuotesResponseModel> { const url = 'https://api.tryto.cn/djt/text32'; return this.http.get<GetQuotesResponseModel>(url) .pipe( retry(3), // 重试三次 catchError(this.handleError) // 捕获错误信息 ); } 4.3、请求和响应拦截在向服务器发起请求时,一般是需要我们在请求头中添加上授权的 token 信息,与其当后端接口返回我们无权访问时再来处理,是不是可以在发起请求前去进行拦截判断,如果不包含 token 信息,则将允许访问的 token 信息添加到请求中
同样的,当已经定义好后端返回什么信息代表请求出错 or 直接根据后端返回的请求状态码判断请求出错时,完全可以通过对接口返回的响应进行拦截,直接拦截掉请求出错的情况,从而不需要在后续的业务逻辑代码中再进行判断请求是否成功
4.3.1、自定义拦截器在 Angular 中可以新建一个继承于 HttpInterceptor 接口的拦截器类,通过实现 intercept 方法来对请求进行拦截处理
与 ASP.NET Core 中的中间件相似,我们可以在请求中添加多个的拦截器,构成一个拦截器链。当一个拦截器已经处理完成时,需要通过 next 对象将 HTTP 请求传递到下一个拦截器,否则,整个请求将会中断。如果当前的拦截器已经是整个拦截器链的最后一个,则会将请求发送到后端接口
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs/internal/Observable'; import { Injectable } from '@angular/core'; import { tap, finalize } from 'rxjs/operators'; /** * 通过添加 Injectable 特性,表明可以通过依赖注入的方式进行创建 */ @Injectable() export class LoggingInterceptor implements HttpInterceptor { /** * 请求拦截 * @param req http 请求 * @param next 下一个拦截器 */ intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { // 开始时间 const started = Date.now(); let msg: string; // 将 http 请求信息传递给下一个拦截器 return next.handle(req) .pipe( tap( // 捕获当前请求是否成功 or 失败 // 1、通过判断响应的类型是否为 HttpResponse 来判断请求是否成功 event => msg = event instanceof HttpResponse ? '请求成功' : '请求失败', // 2、如果存在了 error 回调,则请求失败 error => msg = '请求失败' ), finalize(() => { const elapsed = Date.now() - started; console.log(`请求方式:${req.method} 请求地址:${req.urlWithParams} 响应耗时:${elapsed} ms 请求结果:${msg}`); })); } }当定义好拦截器后,与其它的自定义服务一样,我们需要添加到根模块的 providers 中,因为可能会存在定义多个拦截器的情况,这里可以通过定义一个 typescript 文件用来导出我们需要添加的拦截器信息