天天看點

Angular2 攔截器,使用記錄子產品中添加providers建立攔截器如果需要注入service 使用如下方式

子產品中添加providers

@NgModule({
providers: [
    HttpService,
    {
      provide: HTTP_INTERCEPTORS,
      useClass: AuthInterceptor,//自定義攔截器的類名
      multi: true,
    },
  ],
})
           

注意multi: true

選項。這是必須的,因為它會告訴 Angular 這個

HTTP_INTERCEPTORS

表示的是一個數組,而不是單個的值。

事件

注意,intercept

和HttpHandler.handle

傳回的可觀察對象并不是Observable<HttpResponse<any>>

,而是Observable<HttpEvent<any>>

。 這是因為攔截器所工作的層級要低于

HttpClient 接口。單個請求會生成多個事件,比如表示上傳和下載下傳過程的事件。 HttpResponse

類實際上本身也是一個事件,隻是它的type

是HttpEventType.HttpResponseEvent

攔截器必須透傳所有它不了解或不打算修改的事件。它不能過濾掉自己不準備處理的事件。很多攔截器隻關心要發出的請求,而隻簡單的傳回next

所傳回的事件流,而不修改它。

**

順序

當我們在一個應用中提供了多個攔截器時,Angular 會按照你提供時的順序應用它們(譯注:即子產品的providers

數組中列出的順序)。

不可變性

攔截器要檢查和修改準備發出的請求和接收進來的響應。但是,你可能會驚奇的發現

HttpRequest

類在很大程度上卻是不可變的。

這是有原因的:因為應用可能會重發請求,而攔截器鍊可能會多次處理同一個請求。如果請求是可變的,每次重試時的請求都可能和原始的請求不一樣。而不可變對象可以確定攔截器每次重試時處理的都是同一個請求。

在一種情況下類型安全體系無法在寫攔截器時提供保護 —— 請求體(body)。在攔截器中修改請求體本應是無效的,但類型檢查系統無法發現它。

如果确實需要修改請求體,我們就得自己複制它,修改這個複本,然後使用clone()

來複制這個請求,并使用這個新的請求體。

由于請求都是不可變的,是以不能直接修改它們。要想修改,就使用clone()

函數

建立攔截器

注意implements HttpInterceptor

import {Injectable} from '@angular/core';
import {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest} from '@angular/common/http';

/**什麼也不做,隻是簡單的轉發請求而不做任何修改*/
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req);
  }
}
           
//替換url
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  // This is a duplicate. It is exactly the same as the original.
  const dupReq = req.clone();

  // Change the URL and replace 'http://' with 'https://'
  const secureReq = req.clone({url: req.url.replace('http://', 'https://')});
}
           
import {Injectable} from '@angular/core';
import {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest} from '@angular/common/http';
 
/** 設定新的頭,比如替換token*/
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor(private auth: AuthService) {}
 
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // Get the auth header from the service.
    const authHeader = this.auth.getAuthorizationHeader();
    // Clone the request to add the new header.
    const authReq = req.clone({headers: req.headers.set('Authorization', authHeader)});
    // Pass on the cloned request instead of the original request.
    return next.handle(authReq);
  }
}
           

這種克隆一個請求并設定一組新的請求頭的操作非常常見,是以有了一種快捷寫法:

const authReq = req.clone({setHeaders: {Authorization: authHeader}});
           

如果需要注入service 使用如下方式

constructor(private injector: Injector) { }

this.httpService = this.injector.get(HttpService); // get HttpService within intercept

import {Injectable, Injector} from '@angular/core';
import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {HttpService} from "./http-service.service";
import {Observable} from "rxjs/Observable";

/**
 * @description 攔截器,攔截所有http請求
 *  目前實作功能:
 *    1.請求的header中增加token
 */
@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  private httpService: HttpService;

  constructor(private injector: Injector) {
  }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    this.httpService = this.injector.get(HttpService); // get HttpService  within intercept

    const authReq = request.clone({headers: request.headers.set('token', localStorage.getItem("token"))});
    // Pass on the cloned request instead of the original request.
    return next.handle(authReq);
  }
}

           

繼續閱讀