Angular学习笔记79:Angular 中的拦截器-HttpInterceptor

在项目中,前端需要在每次发送给后端的请求的header中统一添加 token 信息或者其他统一操作,这个时候就用到了拦截器。

在 Angular 中,创建一个拦截器使用到了 @angular/common/http中的HttpInterceptor,实现的具体步骤如下:

创建一个拦截器服务

创建一个服务

因为这按类别分,也是一个服务,所以使用Angular/CLI创建时,执行命令:

ng g s demoInterceptor

执行如下:

service git:(master) ✗ ng g s demoInterceptor
CREATE src/app/public/service/demo-interceptor.service.spec.ts (379 bytes)
CREATE src/app/public/service/demo-interceptor.service.ts (144 bytes)

修改服务实现接口 HttpInterceptor

修改 demo-interceptor.service.ts 如下:

export class DemoInterceptorService implements HttpInterceptor {

  constructor() {
  }

  
}

修改服务实现接口 HttpInterceptor 中的intercept方法

查看接口:HttpInterceptor 的源码,会发现这里需要实现 intercept 方法;

在这里插入图片描述

所以修改 demo-interceptor.service.ts 如下:

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

@Injectable({
  providedIn: 'root'
})
export class DemoInterceptorService implements HttpInterceptor {

  constructor() {
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req);
  }
}

此时一个不进行任何拦截操作的拦截器就创建成功了!

这里会通过next对象,将req 传给下一个拦截器,如果没有下一个拦截器,就会把请求传给HttpClient的后端处理器,从而发送请求,获取数据

给应用注入拦截器

在有HttpClient模块的上级模块,或者同一个模块中注入拦截器,如果在根模块中导入了HttpClientModule,那么就要在根模块中注入拦截器。

修改根模块(app.module.ts)的providers数组

providers: [
    {
      provide: NZ_I18N,
      useValue: zh_CN
    },
    {
      provide: LocationStrategy,
      useClass: HashLocationStrategy
    },
    {
      provide: HTTP_INTERCEPTORS,
      useClass: DemoInterceptorService,
      multi: true
    },
  ],

需要注意的是multi: true这个选项是必须要有的,这个选项是要让Angular 知道HTTP_INTERCEPTORS注入的是一个多个值的数组,而不是单一的一个值。

添加拦截器中的逻辑

由于 HttpRequest 的属性是readonly 的,所以不可以直接修改 HttpRequest,如果需要修改,可以使用clone()方法

在header中添加 Basic 认证信息

修改 demo-interceptor.service.ts 如下:

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

@Injectable({
  providedIn: 'root'
})
export class DemoInterceptorService implements HttpInterceptor {

  constructor() {
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const basicParam = btoa('demoBasic');
    const request = req.clone({headers: req.headers.append('Authorization', 'Basic ' + basicParam)});
    return next.handle(request);
  }
}

这里的basicParam 是通过btoa()方法将'demoBasic'字符串转换成base64,request是将原有的 HttpRequest 增加了Basic 认证信息以后克隆新的request,在通过next.handle将这个新的 HttpRequest 传给下一个拦截器(如果有的话),或者传给 HttpClient 的后端处理器。

清空请求体

当需要判断某个请求需要清空请求体的时候,需要将克隆后的请求体的body 设置为null而不是undefined,设置为undefined,请求体是保持不变的。

具体如下:

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

@Injectable({
  providedIn: 'root'
})
export class DemoInterceptorService implements HttpInterceptor {

  constructor() {
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // 增加Basic认证
    const basicParam = btoa('demoBasic');
    const request = req.clone({headers: req.headers.append('Authorization', 'Basic ' + basicParam)});
    // 清空请求体
    const requestNoBody = req.clone({body: null});
    return next.handle(requestNoBody);
  }
}

捕获错误

有时需要处理请求发生错误;

具体如下:

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

@Injectable({
  providedIn: 'root'
})
export class DemoInterceptorService implements HttpInterceptor {

  constructor() {
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // 增加Basic认证
    const basicParam = btoa('demoBasic');
    const request = req.clone({headers: req.headers.append('Authorization', 'Basic ' + basicParam)});
    // 清空请求体
    const requestNoBody = req.clone({body: null});
    return next.handle(request).pipe(catchError((error: HttpErrorResponse) => this.handleErrorResponse(error)));
  }

  private handleErrorResponse(event: HttpResponse<any> | HttpErrorResponse): Observable<any> {
    // 处理 event
    // ...
    // ...
    return throwError(event);
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值