Angular使用HTTP攔截器

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

相關文章
相關標籤/搜索