AngularHttpClient:拦截器
介绍
Angular 的 HttpInterceptor
提供了一种机制来拦截和/或改变传出请求或传入响应。 除了前端之外,它们与具有 Express 等框架的中间件的概念非常相似。 拦截器对于缓存和日志记录等功能非常有用。
注意:这里的内容适用于Angular 4.3+。
在本文中,您将了解如何在 Angular 项目中使用 HttpInterceptor
。
基本设置
要实现拦截器,您需要创建一个可注入的类并实现 HttpInterceptor
。 该类应定义 intercept
方法以正确实现 HttpInterceptor
。 拦截方法接受两个参数,request
和 next
,并返回一个 HttpEvent
类型的 observable。
request
是请求对象本身,属于HttpRequest
类型。next
是 HTTP 处理程序,类型为HttpHandler
。 处理程序有一个handle
方法,它返回我们想要的HttpEvent
observable。
下面是一个基本的拦截器实现。 这个特定的拦截器简单地使用 RxJS do
运算符将请求的 filter
查询参数的值和 HttpEvent
状态记录到控制台。 do
运算符对于以下副作用很有用:
拦截器/my.interceptor.ts
import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpHandler, HttpRequest, HttpEvent, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs/Observable'; import 'rxjs/add/operator/do'; @Injectable() export class MyInterceptor implements HttpInterceptor { intercept( req: HttpRequest<any>, next: HttpHandler ): Observable<HttpEvent<any>> { return next.handle(req).do(evt => { if (evt instanceof HttpResponse) { console.log('---> status:', evt.status); console.log('---> filter:', req.params.get('filter')); } });
为了连接我们的拦截器,让我们使用 HTTP_INTERCEPTORS
令牌在 app 模块或功能模块中提供它:
app.module.ts
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; import { MyInterceptor } from './interceptors/my.interceptor';
多个拦截器
您可以使用以下内容定义多个拦截器:
providers: [ { provide: HTTP_INTERCEPTORS, useClass: MyInterceptor, multi: true }, { provide: HTTP_INTERCEPTORS, useClass: MySecondInterceptor, multi: true } ],
拦截器将按照它们被提供的顺序被调用。 因此,根据上述情况,MyInterceptor
将首先处理 HTTP 请求。
修改请求
HttpRequest
对象是不可变的,因此为了修改它们,我们需要先制作一个副本,然后修改副本并在修改后的副本上调用 handle
。 请求对象的 clone
方法可以很方便地做到这一点。 这是一个简单的拦截器,它将 filter
查询参数设置为 completed
的值:
@Injectable() export class MyInterceptor implements HttpInterceptor { intercept( req: HttpRequest<any>, next: HttpHandler ): Observable<HttpEvent<any>> { const duplicate = req.clone({ params: req.params.set('filter', 'completed') }); return next.handle(duplicate); } }
这是拦截器的最后一个示例,它将请求正文中每个出现的单词 pizza
更改为披萨表情符号 (🍕)。 没有正文的请求只会通过返回带有 return next.handle(req)
的原始请求来传递:
@Injectable() export class MyInterceptor implements HttpInterceptor { intercept( req: HttpRequest<any>, next: HttpHandler ): Observable<HttpEvent<any>> { if (req.body) { const duplicate = req.clone({ body: req.body.replace(/pizza/gi, '🍕') }); return next.handle(duplicate); } return next.handle(req); } }