在前端開發的過程當中,通常經過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