Angular 拦截器教程

概述

在 Angular 应用中,拦截器(Interceptor)是一个强大的工具,用于拦截和处理 HTTP 请求和响应。拦截器可以用于多种用途,如添加认证头、处理错误、缓存响应等。本教程将详细介绍 Angular 拦截器的概念、使用方法以及如何在实际项目中应用它们。

1. 拦截器的基本概念

1.1 什么是拦截器?

拦截器是 Angular 提供的一种机制,允许你在 HTTP 请求发送之前或响应返回之后对其进行拦截和处理。拦截器可以用于修改请求或响应,或者在请求或响应过程中执行一些额外的逻辑。

1.2 拦截器的用途

  • 认证和授权:在请求头中添加认证令牌。
  • 错误处理:统一处理 HTTP 错误。
  • 日志记录:记录请求和响应的详细信息。
  • 缓存:缓存响应以提高性能。
  • 请求重试:在请求失败时自动重试。

2. 创建一个简单的拦截器

2.1 创建拦截器类

首先,我们需要创建一个拦截器类。拦截器类需要实现 HttpInterceptor 接口,并定义 intercept 方法。

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 authToken = 'your-auth-token';
    const authReq = req.clone({
      headers: req.headers.set('Authorization', `Bearer ${authToken}`)
    });
    return next.handle(authReq);
  }
}

2.2 注册拦截器

拦截器需要在 Angular 模块中注册。通常,我们会在 AppModule 中注册拦截器。

import { NgModule } from '@angular/core';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { AuthInterceptor } from './auth.interceptor';

@NgModule({
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
  ]
})
export class AppModule { }

2.3 使用拦截器

一旦拦截器被注册,所有通过 HttpClient 发送的请求都会被拦截。你可以在 intercept 方法中添加任何你需要的逻辑。

3. 拦截器的实践应用

3.1 添加认证头

在实际应用中,你可能需要为每个请求添加一个认证令牌。以下是一个示例:

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  const authToken = localStorage.getItem('authToken');
  if (authToken) {
    const authReq = req.clone({
      headers: req.headers.set('Authorization', `Bearer ${authToken}`)
    });
    return next.handle(authReq);
  }
  return next.handle(req);
}

3.2 错误处理

你可以使用拦截器来统一处理 HTTP 错误。例如,当请求失败时,你可以显示一个错误消息。

import { catchError } from 'rxjs/operators';
import { throwError } from 'rxjs';

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  return next.handle(req).pipe(
    catchError((error: any) => {
      console.error('HTTP Error:', error);
      return throwError(error);
    })
  );
}

3.3 请求重试

在某些情况下,你可能希望在请求失败时自动重试。你可以使用 retry 操作符来实现这一点。

import { retry } from 'rxjs/operators';

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  return next.handle(req).pipe(
    retry(2) // 重试两次
  );
}

4. 实践练习

4.1 创建一个日志拦截器

创建一个拦截器,用于记录所有 HTTP 请求和响应的详细信息。你可以使用 console.log 来记录这些信息。

import { tap } from 'rxjs/operators';

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  console.log('Request:', req);
  return next.handle(req).pipe(
    tap(event => {
      console.log('Response:', event);
    })
  );
}

4.2 实现一个缓存拦截器

创建一个拦截器,用于缓存 GET 请求的响应。你可以使用 localStorage 或 sessionStorage 来存储缓存数据。

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  if (req.method === 'GET') {
    const cachedResponse = localStorage.getItem(req.url);
    if (cachedResponse) {
      return new Observable(observer => {
        observer.next(JSON.parse(cachedResponse));
        observer.complete();
      });
    }
  }
  return next.handle(req).pipe(
    tap(event => {
      if (event instanceof HttpResponse && req.method === 'GET') {
        localStorage.setItem(req.url, JSON.stringify(event));
      }
    })
  );
}

5. 总结

拦截器是 Angular 中一个非常强大的工具,可以帮助你统一处理 HTTP 请求和响应。通过本教程,你应该已经掌握了如何创建和使用拦截器,以及如何在实际项目中应用它们。拦截器的灵活性使得它们可以用于多种用途,如认证、错误处理、日志记录和缓存等。

6. 进一步学习

  • 多拦截器:Angular 支持多个拦截器,你可以按顺序注册它们,并按顺序执行。
  • 异步操作:拦截器可以执行异步操作,如从服务器获取认证令牌。
  • 高级主题:探索如何使用拦截器实现更复杂的逻辑,如请求合并、响应转换等。

通过不断实践和学习,你将能够更好地利用 Angular 拦截器来提升应用的性能和安全性。