interceptorManager
拦截器是一种强大的机制,可用于拦截和修改 HTTP 请求与响应,与 Express.js 中的中间件非常相似。拦截器是在请求发送前和响应接收前执行的函数,适用于日志记录、修改请求头、修改响应等多种场景。
Axios 中拦截器管理器的核心实现位于 lib/core/InterceptorManager.js。
文件定义了一个 InterceptorManager 类,它采用职责链模式和观察者模式,用于管理请求和响应拦截器,提供了添加、移除和遍历拦截器的方法。
源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| import utils from '../utils.js';
class InterceptorManager { constructor() { this.handlers = []; }
use(fulfilled, rejected, options) { this.handlers.push({ fulfilled, rejected, synchronous: options ? options.synchronous : false, runWhen: options ? options.runWhen : null, }); return this.handlers.length - 1; }
eject(id) { if (this.handlers[id]) { this.handlers[id] = null; } }
clear() { if (this.handlers) { this.handlers = []; } }
forEach(fn) { utils.forEach(this.handlers, function forEachHandler(h) { if (h !== null) { fn(h); } }); } }
export default InterceptorManager;
|
执行顺序
拦截器管理器本身不关心执行顺序,只负责存储和遍历。真正决定顺序逻辑在 /lib/core/Axios.js 的 request 方法中。默认情况下:
请求拦截器与响应拦截器的执行顺序相反
请求拦截器按逆序执行(LIFO——后进先出)。最后添加的请求拦截器最先执行。
响应拦截器按添加顺序执行(FIFO——先进先出)。最先添加的响应拦截器最先执行。
拦截器执行逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
|
const requestInterceptorChain = [];
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) { ... if (legacyInterceptorReqResOrdering) { requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected); } else { requestInterceptorChain.push(interceptor.fulfilled, interceptor.rejected); } ... });
if (!synchronousRequestInterceptors) { const chain = [dispatchRequest.bind(this), undefined]; chain.unshift(...requestInterceptorChain); chain.push(...responseInterceptorChain); len = chain.length;
promise = Promise.resolve(config);
while (i < len) { promise = promise.then(chain[i++], chain[i++]); }
return promise; }
len = requestInterceptorChain.length;
let newConfig = config;
while (i < len) { const onFulfilled = requestInterceptorChain[i++]; const onRejected = requestInterceptorChain[i++]; try { newConfig = onFulfilled(newConfig); } catch (error) { onRejected.call(this, error); break; } }
|
this.handlers
InterceptorManager 类的核心属性是 handlers,它是一个数组,用于存储所有注册的拦截器。每个拦截器按注册顺序存储,执行时也是按此顺序,数组索引作为拦截器的 ID。
每个拦截器对象包含以下属性:
fulfilled:成功回调函数,用于处理成功响应。
rejected:失败回调函数,用于处理失败响应。
synchronous:是否同步执行,默认值为 false,默认被视为异步执行。
runWhen:如果你希望根据运行时条件决定是否执行某个拦截器,可以在选项对象中添加 runWhen 函数。仅当 runWhen 返回 false 时,拦截器不会执行。默认值为 null,执行拦截器。
use(…) {}
添加拦截器,基本用法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| const instance = axios.create();
instance.interceptors.request.use(function (config) { return config; }, function (error) { return Promise.reject(error); }, { runWhen: function(config) { return config.method === 'get'; } });
instance.interceptors.response.use(function (response) { return response; }, function (error) { return Promise.reject(error); });
|
eject(id) {}
移除拦截器方法,根据拦截器 ID 移除对应的拦截器。移除时,将拦截器数组中的空位填充为 null,不是删除数组元素而是设置为 null,可保持其他拦截器的 ID 不变(如果删除元素,后续 ID 会变化)。
使用示例:
1 2
| const myInterceptor = instance.interceptors.request.use(function () {}); instance.interceptors.request.eject(myInterceptor);
|
clear() {}
重置 this.handlers 为空数组,即清空所有拦截器。调用后,所有拦截器将被移除,包括已移除的拦截器。
使用示例:
1
| instance.interceptors.request.clear();
|