Angular HttpInterceptor攔截器 多情景應(yīng)用

HttpInterceptor桩引,是Angular提供用于在全局應(yīng)用程序級(jí)別處理HTTP請(qǐng)求的內(nèi)置工具已慢,攔截并處理HttpRequest或HttpResponse入挣。攔截器在實(shí)戰(zhàn)中的作用有很多移宅,比如:統(tǒng)一配置網(wǎng)關(guān)地址虎忌,設(shè)置Http請(qǐng)求頭泡徙,處理Http請(qǐng)求返回?cái)?shù)據(jù),統(tǒng)一錯(cuò)誤處理等都是常見的需求膜蠢。

這里介紹三種不同的攔截器的實(shí)現(xiàn):

  • 處理Http請(qǐng)求頭 (Http Request Headers)
  • 處理Http響應(yīng) (Http Response)
  • Http錯(cuò)誤處理 (Http Error)
    先看一下攔截器的最基本的實(shí)現(xiàn)
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpEvent, HttpResponse, HttpRequest, HttpHandler } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class CustomInterceptor implements HttpInterceptor {
  public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req);
  }
}

要?jiǎng)?chuàng)建一個(gè)自定義攔截器堪藐,我們需要實(shí)現(xiàn) @angular/common/http中提供的 HttpInterceptor。每一個(gè)通過HttpClient調(diào)用的請(qǐng)求挑围,都會(huì)觸發(fā)攔截器調(diào)用intercept()方法礁竞。當(dāng)調(diào)用intercept()方法時(shí),Angular會(huì)向httpRequest對(duì)象傳遞一個(gè)引用對(duì)象杉辙。然后我們可以根據(jù)需要修改它模捂。完成處理之后,調(diào)用next蜘矢,將更新后的請(qǐng)求返回到應(yīng)用程序狂男。
我們需要將攔截器其注冊(cè)為一個(gè)多提供者,因?yàn)樵谝粋€(gè)應(yīng)用程序中可以運(yùn)行多個(gè)攔截器硼端。注:攔截器將只攔截使用HttpClient服務(wù)發(fā)出的請(qǐng)求并淋。

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';

import { CustomInterceptor } from './custom.interceptor';
import { AppComponent } from './app.component';

@NgModule({
  imports:  [BrowserModule, HttpClientModule ],
  declarations: [ AppComponent ],
  bootstrap: [ AppComponent ],
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: CustomInterceptor, multi: true }
  ]
})
export class AppModule { }

下面根據(jù)我們的需求實(shí)現(xiàn)我們的Http攔截器

處理Http請(qǐng)求頭 (Http Request Headers Interceptor)

通常我們處理Http請(qǐng)求的時(shí)候,需要在請(qǐng)求頭中加入一些身份驗(yàn)證信息珍昨,比如token,我們可以通過攔截器為所有的請(qǐng)求加上token信息

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

@Injectable()
export class HeaderInterceptor implements HttpInterceptor {

    public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return next.handle(this.addToken(req, 'bearer my token'));
    }

    private addToken(req: HttpRequest<any>, token: string): HttpRequest<any> {
        return req.clone({ setHeaders: { Authorization: token } });
    }
}

創(chuàng)建一個(gè)Http請(qǐng)求县耽,來驗(yàn)證我們添加的token

  constructor(private httpClient: HttpClient) {
        this.httpClient.get('/assets/json/data.json').subscribe(ret => {
            // TODO:
        });
    }
http-req-header.png

處理Http響應(yīng) (Http Response Interceptor)

當(dāng)我們需要對(duì)Http請(qǐng)求的返回?cái)?shù)據(jù)進(jìn)行統(tǒng)一處理時(shí),例如镣典,當(dāng)返回結(jié)果是如下格式兔毙,status為200的時(shí)候,我們只保留我們需要的信息兄春。

{
  "data": [
      { "id": 1, "name": "趙錢" },
      { "id": 2, "name": "孫李" },
      { "id": 3, "name": "周吳" },
      { "id": 4, "name": "鄭王" }
  ],
  "requestDatetime": "1949-10-01"
}

根據(jù)上面的需求澎剥,來新增一個(gè)ResponseHandlerInterceptor

import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { filter, map } from 'rxjs/operators';

@Injectable()
export class ResponseHandlerInterceptor implements HttpInterceptor {

    public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return next.handle(req).pipe(
            filter(event => event instanceof HttpResponse && event.status === 200),
            map((event: HttpResponse<any>) => event.clone({ body: event.body.data }))
        );
    }
}

上面的代碼中,當(dāng)返回的數(shù)據(jù)狀態(tài)是200的時(shí)候赶舆,我們只返回body中我們需要的data數(shù)據(jù)哑姚。

Http錯(cuò)誤處理 (Http Error Interceptor)

在Http請(qǐng)求中,我們需要對(duì)錯(cuò)誤情況進(jìn)行統(tǒng)一處理芜茵,這時(shí)候叙量,我們也可以借助攔截器實(shí)現(xiàn)(錯(cuò)誤提示或者重試等)。

import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, throwError } from 'rxjs';
import { catchError, retry } from 'rxjs/operators';

@Injectable()
export class ErrorHandlerInterceptor implements HttpInterceptor {
    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

        return next.handle(req).pipe(
            catchError(error => {
                switch (error.status) {
                    case 401: // Unauthorized
                        // todo
                        break;
                    case 403: // Forbidden
                        // todo
                        break;
                    default:
                        // todo
                        return throwError(error);
                }
            }),
            retry(3)
        );
    }
}

在上面的ErrorHandlerInterceptor攔截器會(huì)攔截http請(qǐng)求的錯(cuò)誤情況九串,我們可以根據(jù)具體的業(yè)務(wù)需求進(jìn)行處理绞佩,也可以通過retry(3)進(jìn)行錯(cuò)誤重試(3表示重試三次)
當(dāng)然寺鸥,創(chuàng)建的時(shí)候要記得配置注入

···
providers: [
        {
            provide: HTTP_INTERCEPTORS,
            useClass: HeaderInterceptor,
            multi: true
        },
        {
            provide: HTTP_INTERCEPTORS,
            useClass: ResponseHandlerInterceptor,
            multi: true
        },
        {
            provide: HTTP_INTERCEPTORS,
            useClass: ErrorHandlerInterceptor,
            multi: true
        }
    ]
···

HttpInterceptor 官方鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市品山,隨后出現(xiàn)的幾起案子胆建,更是在濱河造成了極大的恐慌,老刑警劉巖肘交,帶你破解...
    沈念sama閱讀 212,686評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件笆载,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡酸些,警方通過查閱死者的電腦和手機(jī)宰译,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,668評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來魄懂,“玉大人沿侈,你說我怎么就攤上這事∈欣酰” “怎么了缀拭?”我有些...
    開封第一講書人閱讀 158,160評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)填帽。 經(jīng)常有香客問我蛛淋,道長(zhǎng),這世上最難降的妖魔是什么篡腌? 我笑而不...
    開封第一講書人閱讀 56,736評(píng)論 1 284
  • 正文 為了忘掉前任褐荷,我火速辦了婚禮,結(jié)果婚禮上嘹悼,老公的妹妹穿的比我還像新娘叛甫。我一直安慰自己,他們只是感情好杨伙,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,847評(píng)論 6 386
  • 文/花漫 我一把揭開白布其监。 她就那樣靜靜地躺著,像睡著了一般限匣。 火紅的嫁衣襯著肌膚如雪抖苦。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,043評(píng)論 1 291
  • 那天米死,我揣著相機(jī)與錄音锌历,去河邊找鬼。 笑死峦筒,一個(gè)胖子當(dāng)著我的面吹牛辩涝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播勘天,決...
    沈念sama閱讀 39,129評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了脯丝?” 一聲冷哼從身側(cè)響起商膊,我...
    開封第一講書人閱讀 37,872評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎宠进,沒想到半個(gè)月后晕拆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,318評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡材蹬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,645評(píng)論 2 327
  • 正文 我和宋清朗相戀三年实幕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片堤器。...
    茶點(diǎn)故事閱讀 38,777評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡昆庇,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出闸溃,到底是詐尸還是另有隱情整吆,我是刑警寧澤,帶...
    沈念sama閱讀 34,470評(píng)論 4 333
  • 正文 年R本政府宣布辉川,位于F島的核電站表蝙,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏乓旗。R本人自食惡果不足惜府蛇,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,126評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望屿愚。 院中可真熱鬧汇跨,春花似錦、人聲如沸渺鹦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,861評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽毅厚。三九已至塞颁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間吸耿,已是汗流浹背祠锣。 一陣腳步聲響...
    開封第一講書人閱讀 32,095評(píng)論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留咽安,地道東北人伴网。 一個(gè)月前我還...
    沈念sama閱讀 46,589評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像妆棒,于是被迫代替她去往敵國和親澡腾。 傳聞我的和親對(duì)象是個(gè)殘疾皇子沸伏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,687評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容