axios之interceptorManager.js源码

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 = [];
}

/**
* 注册拦截器方法
* @param {function} fulfilled 成功回调函数
* @param {function} rejected 失败回调函数
* @param {object} options 控制拦截器行为
* @returns {number} 拦截器 ID
*/
use(fulfilled, rejected, options) {
// 将拦截器对象存入 `handlers` 数组
this.handlers.push({
fulfilled,
rejected,
synchronous: options ? options.synchronous : false,
runWhen: options ? options.runWhen : null,
});
return this.handlers.length - 1;
}

// 根据拦截器 ID 移除对应的拦截器
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.jsrequest 方法中。默认情况下:

请求拦截器与响应拦截器的执行顺序相反
请求拦截器按逆序执行(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
// lib/core/Axios.js

// 请求拦截器链
const requestInterceptorChain = [];

this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
...
// 根据 legacyInterceptorReqResOrdering 决定请求拦截器执行顺序
// 如果为 true,反转拦截器链,后添加的请求拦截器放链首(LIFO——后进先出)
// 如果为 false,则按添加顺序添加(FIFO——先进先出)
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) {
// 只在请求方法为 GET 时执行该拦截器
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();

axios之interceptorManager.js源码
https://www.my-web.cn/axios/interceptorManager/
发布于
2026年4月30日
许可协议