在 Angular 应用中,HttpClient 负责处理 HTTP 请求的发送和响应的接收。如果我们需要为发出的每一个请求,增加一个请求头信息(例如,访问令牌),那么,我们可能需要为每个请求发送方法添加相同的一段代码。
getBooks(): Observable<Book[]> {
return this.http.get<Book[]>(this.booksUrl, {
headers: new HttpHeaders({'Authorization': accessToken'})
});
}
很快,这个方法会让代码变得臃肿,难于测试和维护。Angular 提供了拦截器,可以优雅地解决这个问题。
应用场景
Angular 的拦截器可以在下列场景下使用:
- 修改 HTTP 请求头的信息
- 展示页面/数据正在加载
- 记录 HTTP 通信的日志
拦截器
在 Angular 应用中,拦截器是一个实现了 HttpInterceptor 接口的服务类。每个拦截器都要实现 HttpInterceptor 接口定义的 intercept() 方法。在 intercept() 方法中,可以对 HTTP 请求进行识别和处理。
HttpInterceptor 接口定义:
interface HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>
}
拦截器的定义:
/** Pass untouched request through to the next request handler. */
@Injectable()
export class SomeInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler):
Observable<HttpEvent<any>> {
return next.handle(req);
}
}
创建拦截器
现在,我们创建一个拦截器,为每一个发出的 HTTP 请求,在其请求头中添加一个访问令牌。
- 使用 Angular CLI 命令,创建一个认证拦截器。
ng generate interceptor authn
刚刚创建的拦截器:
import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable()
export class AuthnInterceptor implements HttpInterceptor {
constructor() {}
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
return next.handle(request);
}
}
- 注册 authn 拦截器。拦截器需要注册后,才可以使用。下面,在 AppModule 中,对其进行注册。
...
@NgModule({
imports: [
...
HttpClientModule,
...
],
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: AuthnInterceptor, multi: true }
],
bootstrap: [AppComponent]
})
export class AppModule { }
如果一个模块需要注册拦截器,那该模块必须导入 HttpClientModule 模块。
在注册拦截器时,我们使用了 multi 属性,并设置其值为 true. multi: true,表示当前注册的拦截器,可以实例化多个实例对象。
- 实现接口
intercept方法。
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
const authnReq = request.clone({
setHeaders: {
Authorization: 'accessToken'
}
});
return next.handle(authnReq);
}
因为作为参数的 HttpRequest 对象是不可以修改的,所以要修改 request 对象,就需要使用他的 clone 方法创建一个新的请求对象。同理, HttpHeaders 对象也不可以修改,需要使用 setHeaders 方法进行更新。












网友评论