告别重复编码:Angular拦截器让HTTP请求处理自动化

告别重复编码:Angular拦截器让HTTP请求处理自动化

【免费下载链接】angular Angular是由Google开发和维护的一个现代前端JavaScript框架,具有高效的数据绑定、模块化架构、依赖注入等特性,适合构建大型企业级单页应用。 【免费下载链接】angular 项目地址: https://gitcode.com/GitHub_Trending/an/angular

你还在为每个HTTP请求重复添加认证Token?还在为分散的错误处理逻辑头疼?Angular拦截器(Interceptor)将彻底解决这些问题!本文将带你掌握如何使用拦截器实现请求统一处理,包括认证头自动附加、全局错误捕获、请求/响应日志记录等核心场景,让你的代码更简洁、更易维护。

什么是Angular拦截器

Angular拦截器是一种中间件机制,用于在HTTP请求发送前和响应返回后进行统一处理。它基于HttpInterceptor接口实现,允许开发者拦截、修改和转换HTTP请求/响应,而无需在每个请求处重复编写相同逻辑。

拦截器的核心接口定义在packages/common/http/src/interceptor.ts中:

export interface HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>;
}

拦截器工作流程

拦截器通过链式调用处理请求,每个拦截器可以决定是否修改请求、传递给下一个拦截器或直接返回响应。以下是典型的拦截器链工作流程:

mermaid

实战:创建你的第一个拦截器

步骤1:实现拦截器类

创建一个认证拦截器,自动为所有请求添加Bearer Token:

// src/app/interceptors/auth.interceptor.ts
import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor() {}

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    // 从本地存储获取token
    const token = localStorage.getItem('auth_token');
    
    if (token) {
      // 克隆请求并添加认证头
      const authReq = request.clone({
        headers: request.headers.set('Authorization', `Bearer ${token}`)
      });
      return next.handle(authReq);
    }
    
    return next.handle(request);
  }
}

步骤2:注册拦截器

在应用模块中通过HTTP_INTERCEPTORS令牌注册拦截器:

// src/app/app.module.ts
import { NgModule } from '@angular/core';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { AuthInterceptor } from './interceptors/auth.interceptor';

@NgModule({
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: AuthInterceptor,
      multi: true  // 允许多个拦截器并存
    }
  ]
})
export class AppModule { }

HTTP_INTERCEPTORS令牌定义在packages/common/http/src/interceptor.ts中,是一个多提供商令牌,支持同时注册多个拦截器。

高级应用场景

1. 全局错误处理

创建错误拦截器统一处理API错误:

// src/app/interceptors/error.interceptor.ts
import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor,
  HttpErrorResponse
} from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { Router } from '@angular/router';

@Injectable()
export class ErrorInterceptor implements HttpInterceptor {

  constructor(private router: Router) {}

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    return next.handle(request).pipe(
      catchError((error: HttpErrorResponse) => {
        switch (error.status) {
          case 401:
            // 未授权,重定向到登录页
            this.router.navigate(['/login']);
            break;
          case 403:
            // 禁止访问,显示提示
            alert('您没有权限访问该资源');
            break;
          case 500:
            // 服务器错误,记录日志
            console.error('服务器错误:', error.message);
            break;
        }
        return throwError(() => error);
      })
    );
  }
}

2. 请求/响应日志记录

实现日志拦截器跟踪API调用:

// src/app/interceptors/log.interceptor.ts
import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';

@Injectable()
export class LogInterceptor implements HttpInterceptor {

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    const startTime = Date.now();
    
    // 记录请求信息
    console.log(`请求: ${request.method} ${request.url}`);
    
    return next.handle(request).pipe(
      tap({
        next: (event) => {
          if (event.type === 4) { // 响应完成事件
            const duration = Date.now() - startTime;
            console.log(`响应: ${request.url} (${duration}ms)`);
          }
        },
        error: (error) => {
          console.error(`请求失败: ${request.url}`, error);
        }
      })
    );
  }
}

拦截器注册与执行顺序

多个拦截器的注册顺序决定了执行顺序,先注册的拦截器先执行请求拦截,后执行响应拦截:

// 注册顺序: AuthInterceptor -> LogInterceptor -> ErrorInterceptor
providers: [
  { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
  { provide: HTTP_INTERCEPTORS, useClass: LogInterceptor, multi: true },
  { provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true }
]

执行流程:

  • 请求阶段:AuthInterceptor → LogInterceptor → ErrorInterceptor → 后端
  • 响应阶段:ErrorInterceptor → LogInterceptor → AuthInterceptor → 应用代码

注意事项与最佳实践

  1. 不可变性:始终克隆请求对象而非直接修改,因为HttpRequest是不可变的
  2. 依赖注入:拦截器支持依赖注入,但避免循环依赖
  3. 性能考虑:避免在拦截器中执行耗时操作,影响请求响应速度
  4. 拦截器范围:在根模块注册的拦截器作用于整个应用,特性模块注册的仅作用于该模块
  5. 测试策略:使用Angular测试工具packages/core/testing/src/testing.ts测试拦截器逻辑

总结

Angular拦截器通过集中处理HTTP通信逻辑,显著提升了代码复用性和可维护性。本文介绍的认证处理、错误捕获和日志记录等场景只是拦截器能力的冰山一角,你还可以用它实现缓存、请求节流、API版本控制等高级功能。

立即重构你的HTTP请求处理逻辑,体验拦截器带来的开发效率提升吧!更多高级用法可参考Angular官方文档packages/docs/和API参考goldens/public-api/core/

【免费下载链接】angular Angular是由Google开发和维护的一个现代前端JavaScript框架,具有高效的数据绑定、模块化架构、依赖注入等特性,适合构建大型企业级单页应用。 【免费下载链接】angular 项目地址: https://gitcode.com/GitHub_Trending/an/angular

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值