AngularHttpClient:拦截器

来自菜鸟教程
跳转至:导航、​搜索

介绍

Angular 的 HttpInterceptor 提供了一种机制来拦截和/或改变传出请求或传入响应。 除了前端之外,它们与具有 Express 等框架的中间件的概念非常相似。 拦截器对于缓存和日志记录等功能非常有用。

注意:这里的内容适用于Angular 4.3+。


在本文中,您将了解如何在 Angular 项目中使用 HttpInterceptor

基本设置

要实现拦截器,您需要创建一个可注入的类并实现 HttpInterceptor。 该类应定义 intercept 方法以正确实现 HttpInterceptor。 拦截方法接受两个参数,requestnext,并返回一个 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 =&gt; {
  if (evt instanceof HttpResponse) {
    console.log('---&gt; status:', evt.status);
    console.log('---&gt; 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);
  }
}