axios之adapters.js源码

adapters.js

adapters.js 是 Axios 实现跨平台请求的核心,位于 lib/adapters/adapters.js,负责管理和解析不同平台的适配器(http、xhr、fetch)。

适配器允许你自定义 axios 处理请求数据的方式。默认情况下,axios 使用 ['xhr', 'http', 'fetch'] 的有序优先级列表,并选择当前环境支持的第一个适配器。实际上,这意味着在浏览器中使用 xhr ,在 Node.js 中使用 http ,在两者均不可用的环境(如 Cloudflare Workers 或 Deno)中使用 fetchfetch 适配器是 1.7.0 版本中引入的新适配器。

  • http 适配器环境判断逻辑
1
2
3
4
5
6
7
8
9
/lib/adapters/http.js

const isHttpAdapterSupported =
typeof process !== 'undefined' && utils.kindOf(process) === 'process';

export default isHttpAdapterSupported &&
function httpAdapter(config) {
...
}
  • xhr 适配器环境判断逻辑
1
2
3
4
5
6
7
8
/lib/adapters/xhr.js

const isXHRAdapterSupported = typeof XMLHttpRequest !== 'undefined';

export default isXHRAdapterSupported &&
function (config) {
...
}

源码

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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import utils from '../utils.js';
import httpAdapter from './http.js';
import xhrAdapter from './xhr.js';
import * as fetchAdapter from './fetch.js';
import AxiosError from '../core/AxiosError.js';

// 已知适配器
const knownAdapters = {
http: httpAdapter,
xhr: xhrAdapter,
fetch: {
get: fetchAdapter.getFetch,
},
};

// 为适配器命名,以便于调试和识别
utils.forEach(knownAdapters, (fn, value) => {
if (fn) {
try {
// 为适配器函数添加 name 属性
Object.defineProperty(fn, 'name', { __proto__: null, value });
} catch (e) {
}
// 为适配器函数添加 adapterName 属性
Object.defineProperty(fn, 'adapterName', { __proto__: null, value });
}
});


/**
* 为未知或不受支持的适配器生成一个拒绝原因字符串
* 格式化错误原因,添加 - 前缀
*/
const renderReason = (reason) => `- ${reason}`;

/**
* 检查适配器是否已解析(function、null 或 false)
*/
const isResolvedHandle = (adapter) =>
utils.isFunction(adapter) || adapter === null || adapter === false;

/**
* 从提供的列表中获取第一个合适的适配器。
* 依次尝试每个适配器,直到找到一个支持的适配器为止。
* 如果没有合适的适配器,则抛出AxiosError。
*/
function getAdapter(adapters, config) {
// 将适配器列表转为数组
adapters = utils.isArray(adapters) ? adapters : [adapters];

const { length } = adapters;
let nameOrAdapter;
let adapter;

const rejectedReasons = {};

for (let i = 0; i < length; i++) {
// 遍历适配器列表
nameOrAdapter = adapters[i];
let id;

adapter = nameOrAdapter;

// 判断适配器是否已解析(即是否为函数、null 或 false)
if (!isResolvedHandle(nameOrAdapter)) {
// 从已知适配器中获取适配器函数
adapter = knownAdapters[(id = String(nameOrAdapter)).toLowerCase()];

// 如果适配器不存在,抛出错误
if (adapter === undefined) {
throw new AxiosError(`Unknown adapter '${id}'`);
}
}

// 检查适配器是否可用
// - adapter: 适配器存在
// - utils.isFunction: 检查适配器是否为函数
// - adapter.get(config): 调用适配器的 get 方法,获取适配器实例,fetch适配器需要特殊处理
if (adapter && (utils.isFunction(adapter) || (adapter = adapter.get(config)))) {
break;
}

// 记录当前适配器被拒绝的原因
rejectedReasons[id || '#' + i] = adapter;
}

// 如果没有合适的适配器,抛出错误
if (!adapter) {
const reasons = Object.entries(rejectedReasons).map(
([id, state]) =>
`adapter ${id} ` +
(state === false ? 'is not supported by the environment' : 'is not available in the build')
);

let s = length
? reasons.length > 1
? 'since :\n' + reasons.map(renderReason).join('\n')
: ' ' + renderReason(reasons[0])
: 'as no adapter specified';

throw new AxiosError(
`There is no suitable adapter to dispatch the request ` + s,
'ERR_NOT_SUPPORT'
);
}

// 返回合适的适配器
return adapter;
}

export default {
// 从适配器名称或函数列表中解析出一个适配器函数
getAdapter,

// 暴露所有已知适配器
adapters: knownAdapters,
};

内置适配器

在项目我们一般不会配置 adapter 参数,而是使用默认的配置适配器。

1
2
3
4
5
6
7
8
9
10
11
12
// lib/defaults/index.js
const defaults = {
...
adapter: ['xhr', 'http', 'fetch'],
...
}

// lib/axios.js
function createInstance(defaultConfig) {
const context = new Axios(defaultConfig);
}
const axios = createInstance(defaults);

可以通过 adapter 配置选项按名称选择内置适配器:

1
2
3
4
5
6
7
8
9
10
11
// 使用 fetch 适配器
const instance = axios.create({ adapter: "fetch" });

// 使用 XHR 适配器(浏览器默认)
const instance = axios.create({ adapter: "xhr" });

// 使用 HTTP 适配器(Node.js 默认)
const instance = axios.create({ adapter: "http" });

// 优先使用 fetch 适配器,否则使用 XHR 适配器,最后使用 HTTP 适配器
const instance = axios.create({ adapter: ["fetch", "xhr", "http"] });

自定义适配器

要创建自定义适配器,需要编写一个接受 config 对象并返回 Promise 的函数,该 Promise 需解析为有效的 axios 响应对象。

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
import axios from "axios";
import { settle } from "axios/unsafe/core/settle.js";

function myAdapter(config) {
return new Promise((resolve, reject) => {
fetch(config.url, {
method: config.method?.toUpperCase() ?? "GET",
})
.then(async (fetchResponse) => {
const responseData = await fetchResponse.text();

const response = {
data: responseData,
status: fetchResponse.status,
statusText: fetchResponse.statusText,
headers: Object.fromEntries(fetchResponse.headers.entries()),
config,
request: null,
};

// settle 根据 HTTP 状态码决定是 resolve 还是 reject
settle(resolve, reject, response);
})
.catch(reject);
});
}

const instance = axios.create({ adapter: myAdapter });

axios之adapters.js源码
https://www.my-web.cn/axios/adapter/
发布于
2026年5月13日
许可协议