在前后端分离架构中,拦截器链就像交通枢纽的智能调度系统。我经历过一个电商项目,由于缺乏拦截器管理,代码里散落着大量重复的鉴权逻辑和日志打印,后来用拦截器链重构后,核心业务代码量减少了40%。这种设计模式本质上是通过责任链模式(Chain of Responsibility)实现的管道处理机制,每个拦截器都是管道中的一个处理器。
典型的应用场景包括:
一个健壮的拦截器链需要包含以下要素:
typescript复制interface Interceptor {
preHandle(request: Request): Request | Promise<Request>;
postHandle(response: Response): Response | Promise<Response>;
errorHandler(error: Error): Error | Promise<Error>;
}
class InterceptorChain {
private interceptors: Interceptor[] = [];
addInterceptor(interceptor: Interceptor) {
this.interceptors.push(interceptor);
}
async execute(request: Request) {
let currentRequest = request;
// 请求预处理
for (const interceptor of this.interceptors) {
currentRequest = await interceptor.preHandle(currentRequest);
}
let response: Response;
try {
response = await fetch(currentRequest);
// 响应后处理
for (const interceptor of [...this.interceptors].reverse()) {
response = await interceptor.postHandle(response);
}
return response;
} catch (error) {
// 异常处理
for (const interceptor of [...this.interceptors].reverse()) {
error = await interceptor.errorHandler(error);
}
throw error;
}
}
}
拦截器的执行顺序遵循"先进后出"原则:
这种设计确保了:
typescript复制class PerformanceInterceptor implements Interceptor {
private timers = new WeakMap<Request, number>();
preHandle(request: Request) {
this.timers.set(request, performance.now());
return request;
}
postHandle(response: Response) {
const duration = performance.now() - this.timers.get(response.request);
console.log(`[${response.url}] 耗时: ${duration.toFixed(2)}ms`);
return response;
}
}
typescript复制class RetryInterceptor implements Interceptor {
constructor(private maxRetries = 3) {}
async errorHandler(error: Error) {
if (this.shouldRetry(error)) {
return this.retryRequest(error.request);
}
throw error;
}
private async retryRequest(request: Request) {
for (let i = 0; i < this.maxRetries; i++) {
try {
return await fetch(request);
} catch (retryError) {
if (i === this.maxRetries - 1) throw retryError;
await this.delay(1000 * (i + 1));
}
}
}
}
特别注意:拦截器中引用外部变量时务必使用WeakMap而非普通Map,防止请求对象无法被GC回收
常见错误场景:
解决方案:
typescript复制// 错误示例:未处理异步拒绝
interceptors.forEach(interceptor => {
interceptor.preHandle(request); // 可能丢失异常
});
// 正确示例:使用reduce链式处理
await interceptors.reduce(
(promise, interceptor) => promise.then(req => interceptor.preHandle(req)),
Promise.resolve(request)
);
typescript复制// 根据请求特征动态加载拦截器
function createDynamicChain(request) {
const chain = new InterceptorChain();
if (request.url.includes('/api/')) {
chain.addInterceptor(new AuthInterceptor());
}
if (request.headers.get('X-Request-Metrics')) {
chain.addInterceptor(new MetricsInterceptor());
}
return chain;
}
在主应用和子应用各自维护拦截器链的基础上,通过Proxy模式实现层级调用:
typescript复制class FederatedInterceptorChain {
constructor(private parent: InterceptorChain, private child: InterceptorChain) {}
async execute(request) {
// 先执行父级preHandle
let processed = await parent.execute(request);
// 再执行子级处理
return child.execute(processed);
}
}
在实际项目中,完善的拦截器链可以显著提升以下指标: