angular拦截请求和响应

拦截器的概念想必大家都不陌生,不过这里还是要提一句(凑一点字数):

  • 拦截器就是在我们的请求 发送之前 或 请求返回之后被我们处理之前,先截住。
  • 当然截住之后我们可以对其做一些操作,比如:添加请求头,或者根据响应的状态做出不同的提示 等等。
  • 拦截器为我们节省了很多不必要的操作,代码更加简洁化,更加有逻辑性。

接下来我会举例子,说一下angular的拦截器:

  • 通过拦截器给请求自动添加请求头【先看代码】:
    filename:auth.ts
import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        const token: string = window.localStorage.getItem('token');
        if (token) {
            // 设置请求头
            req = req.clone({
                setHeaders: {
                    'Authorization': `Bearer ${token}`,
                    'Content-Type': 'application/json'
                }
            });
        }
        
        return next.handle(req);
    }
}

上面的代码就是一个简单的拦截请求,并自动给请求添加请求头的例子。

  • 解释:
  • 要实现拦截器,就要实现一个实现了 HttpInterceptor 接口中的 intercept() 方法的类。 intercept 方法会把请求转换成一个最终返回 HTTP 响应体的 Observable

给大家简化一下:就是我们要写拦截器,就一定要写intercept()方法,而且这个方法会把我们处理过的请求返回。

  • 通过代码很容易就看出来,req 指的我们的请求,通过req我们不仅可以拿到我们当前访问的地址url,还可以拿到请求头headers,参数params等,那么 next 是干嘛的呢。
  • next 对象表示拦截器链表中的下一个拦截器。 这个链表中的最后一个 next 对象就是 HttpClient 的后端处理器(backend handler),它会把请求发给服务器,并接收服务器的响应。

给大家简化一下:拦截器拦截都会在传入时检查请求,然后把(可能被修改过的)请求转发给 next 对象的 handle() 方法。在代码里我们把其直接返回了。

  • 最后在说说我们为啥要用req.clone,我前面说了,我们可以通过req的url属性拿到访问的地址,按理来说我们可以这么搞:
// 比如替换http 为 https
req.url = req.url.replace('http://', 'https://');

但是很可惜,typescript 不允许这么搞,因为实现req的HttpRequest是只读属性,所以我们要修改的话,就要先克隆一份:

const secureReq = req.clone({
  url: req.url.replace('http://', 'https://')
});

return next.handle(secureReq)

这个 clone() 方法的哈希型参数允许你在复制出克隆体的同时改变该请求的某些特定属性。

上面的代码解释完了,下面说一下怎么用拦截器:

  1. 我们使用之前要把AuthInterceptor注入一下,在app.moudule.tsprovide里:
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }

  1. 注入完成后我们要怎么使用呢?想必不熟悉angular拦截器的人都有点蒙,我一开也有点蒙,只看auth.ts 中 return了,我们要怎么用呢?
    用法就是直接用
constructor(
	public http:HttpClient
){}

// 如果在没有拦截器之前我们还需要第三个参数 headers手动设置请求头
ngOnInit(){
    this.http.post(url,params,headers)
}

// 现在有了拦截器,我们直接用就行了,headers拦截器会自动帮我们加好
ngOnInit(){
    this.http.post(url,parmas); // 这就可以了
}

下面就在说一下怎么拦截响应,我们可以在响应之后根据响应的状态进行一些其他操作:

// 首先我们多引入一个东西:HttpResponse
import { HttpResponse } from '@angular/common/http';

然后在return next.handle()之后利用管道来进行一个拦截后的操作:

// 注意 tap 和 finalize 是rxjs中操作符,使用时需要引入:
import {tap,finalize} from 'rxjs/operators';

return next.handle(req).pipe(
            tap(event=>{
                if(event instanceof HttpResponse) {
                	// 成功
					console.log('success')
                }
            },error=>{
            	// 失败
                console.log(error)
            }),
            finalize(()=>{
            	// 请求完成
                console.log('complete')
            })
        )

RxJS 的 tap 操作符会捕获请求成功了还是失败了。 RxJS 的 finalize 操作符无论在响应成功还是失败时都会调用(这是必须的) 。


以上就是简单的 angular的拦截器使用了。更多高深的用法,大家还是要多多看angular的官网