在前端开发的过程当中,通常经过HTTP接口与后端进行数据交互,然后端通常会固定一个返回格式,例如:前端
{ "code": 0, "success": true, "message": "", "result":{ "id":9, "title":"", "content":"", "createTime":"2020-11-25 19:22:31", "updateTime":"2020-11-25 19:47:22", "available":true } }
前端在拿到数据后,首先判断是否成功,而后取出数据体显示到页面上,可是每一次都这么去作,几乎都是重复的操做,在后端开发的过程当中,有诸如过滤器、Spring提供的拦截器等工具实现对HTTP请求的统一处理,在前端其实也有相似的东西,Angular框架就提供了拦截器接口:typescript
interface HttpInterceptor { intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> }
能够实现统一的HTTP请求处理,帮助咱们简化代码,而且方便代码的维护,直接放上一个我实际使用过的示例代码:json
import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse, HttpResponseBase } from '@angular/common/http'; import {Observable, of, throwError} from 'rxjs'; import {Injectable} from '@angular/core'; import {catchError, debounceTime, finalize, mergeMap, retry} from 'rxjs/operators'; import {AppService} from '../service/app.service'; /** * 全局HTTP请求拦截器 */ @Injectable() export class AppHttpInterceptor implements HttpInterceptor { // 当前正在通讯中的HTTP请求数量,此值是为了在http请求的过程当中添加加载动画 public processingHttpCount = 0; // 依赖注入 constructor(public appService: AppService) { } intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { // /monitor前缀的不作处理 if (req.url.includes('/monitor')) { return next.handle(req); } //; setTimeout(() => this.appService.showLoadingBar = true); // this.processingHttpCount ++; return next.handle(req.clone({ // 为全部拦截的请求添加一个'/starry'前缀 url: '/starry' + (req.url.startsWith('/') ? req.url : '/' + req.url) })) .pipe( debounceTime(1000), // 失败时重试2次 retry(2), mergeMap((event: any) => { // 处理后端HTTP接口返回结果 if (event instanceof HttpResponseBase) { // HTTP返回代码正常 if (event.status >= 200 && event.status < 400) { // 处理HTTP Response if (event instanceof HttpResponse) { const body = event.body; // 判断后端的成功标志字段是否为true if (body && body.success) { // 取出响应体数据的data部分并继续后续操做(将原有的body替换为了body['result']) return of(new HttpResponse(Object.assign(event, {body: body.result}))); } else { // 抛出异常 throw Error(body.message); } } } } // 其他事件类型不做拦截处理 return of(event); }), catchError((err: HttpErrorResponse) => { // 若是发生5xx异常,显示一个错误信息提示 this.appService.showSnackBar(err.message, 4000); console.error(err.message) return throwError(err); }), finalize(() => { // 最终processingHttpCount减一,而且在减至0的时候移除掉加载动画 setTimeout(() => --this.processingHttpCount === 0 ? this.appService.showLoadingBar = false : this.appService.showLoadingBar = true, 500); })); } }
并将此拦截器注册在Angular模块的provider中去,在providers中添加:后端
{ provide: HTTP_INTERCEPTORS, useClass: AppHttpInterceptor, multi: true }
这样在调用后端接口的时候咱们不用每次再处理后端的返回数据,可直接在返回值中拿到数据体部分去作页面展现,其他的事情就交给拦截器去处理,例如:api
this.httpClient.get('/config/template/' + template).subscribe(data => this.configTemplates.push({template, data}));
至此,就配置好了一个HTTP拦截器,还能够统一处理请求的URL以及异常处理等等,十分方便。官方文档地址:https://angular.io/api/common/http/HttpInterceptor (中文文档将 .io 改成 .cn 便可)
除此以外,对于页面路由,Angular其实也提供了相似的工具,能够对路由以及页面组件进行拦截控制,有机会再做介绍。app