拦截器是一种很常用的东西,作用有很多,比如说设置Http请求头,处理Http请求返回数据,统一错误处理等,angualr里也有拦截器 HttpInterceptor
先实现一个最基本的拦截器
import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpEvent, 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>> { console.log('拦截成功'); return next.handle(req); } }
这个拦截器什么操作也没做,只是单纯的拦截
要使拦截器生效,需要在app.module.ts里注入
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; import { AppComponent } from './app.component'; import { CustomInterceptor } from './http-interceptors/customInterceptor'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, HttpClientModule ], providers: [ { provide: HTTP_INTERCEPTORS, useClass: CustomInterceptor, multi: true } ], bootstrap: [AppComponent] }) export class AppModule { }
测试一下
import { Component, OnInit } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { constructor(private http: HttpClient) {} ngOnInit(): void { this.getData(); } getData() { this.http.get('assets/config.json').subscribe((data) => { console.log('获取数据成功', data); }) } }
拦截成功了
处理Http请求头 (Http Request Headers Interceptor)
通常我们处理http请求的时候,需要在请求头中加入一些身份验证信息,比如说token,我们可以通过拦截器为所有的请求加上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 { intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { return next.handle(this.addToken(req, 'my token')); } addToken(req: HttpRequest<any>, token: string): HttpRequest<any> { return req.clone({ headers: req.headers.set('Authorization', token) }); // 又或者是 req.clone({ setHeaders: { Authorizetion: token } }); } }
然后也要把这个拦截器注入到app.module.ts 里,它才会生效
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; import { AppComponent } from './app.component'; import { CustomInterceptor } from './http-interceptors/customInterceptor'; import { HeaderInterceptor } from './http-interceptors/headerInterceptor'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, HttpClientModule ], providers: [ { provide: HTTP_INTERCEPTORS, useClass: CustomInterceptor, multi: true }, { provide: HTTP_INTERCEPTORS, useClass: HeaderInterceptor, multi: true }, ], bootstrap: [AppComponent] }) export class AppModule { }
看一下请求头,已经生效了
处理Http响应 (Http Response Interceptor)
有的时候我们需要对请求返回的数据处理一下,比如添加一个id,再新建一个响应拦截器
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @Injectable() export class ResponseHandlerInterceptor implements HttpInterceptor { intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { return next.handle(req).pipe( map((event) => { if (event instanceof HttpResponse && event.status === 200) { event.clone({ body: this.addId(event.body) }); } return event; }) ) } addId(data: any) { data.forEach((item: any, index: any) => { item.id = index; }) } }
再把它注入到app.module.ts 里,看一下效果
Id已经成功添加
Http错误处理(Http Error Interceptor)
在Http请求中,我们需要对错误情况进行统一处理,这时候,我们也可以借助拦截器实现(错误提示或重试等)
新建一个错误处理拦截器
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 => { console.log('请求'); let text = '请求失败'; switch (error.status) { case 401: text = '' break; case 403: text = '' break; } return throwError(() => text); }), retry(3) ); } }
把它也注入到app.module.ts 里之后,拦截器生效了
可以看到请求一共发起了4次,第一次失败了之后retry(3)又重新发起了3次请求,最后都失败了之后,抛出错误,retry(3)括号里是几就重新发起几次请求, 而在switch里我们可以对不同的错误情况做出相应处理
最后,如果我们有多个拦截器,一个个注入到app.module.ts里有点麻烦,我们可以把拦截器导入到一个文件里,再把这个文件注入到app.module.ts里,会方便一些
import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { CustomInterceptor } from './customInterceptor'; import { HeaderInterceptor } from './headerInterceptor'; import { ResponseHandlerInterceptor } from './responseHandlerInterceptor'; import { ErrorHandlerInterceptor } from './errorHandlerInterceptor'; export const httpInterceptorProviders = [ { provide: HTTP_INTERCEPTORS, useClass: CustomInterceptor, multi: true }, { provide: HTTP_INTERCEPTORS, useClass: HeaderInterceptor, multi: true }, { provide: HTTP_INTERCEPTORS, useClass: ResponseHandlerInterceptor, multi: true }, { provide: HTTP_INTERCEPTORS, useClass: ErrorHandlerInterceptor, multi: true }, ]; import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { HttpClientModule } from '@angular/common/http'; import { AppComponent } from './app.component'; import { httpInterceptorProviders } from './http-interceptors/index'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, HttpClientModule ], providers: [ httpInterceptorProviders ], bootstrap: [AppComponent] }) export class AppModule { }