ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

axios.create() 深入解析:构建预配置 Axios 实例,从多服务基址到源码合并机制

axios.create() 深入解析:构建预配置 Axios 实例,从多服务基址到源码合并机制 axios.create() 深入解析构建预配置 Axios 实例从多服务基址到源码合并机制【免费下载链接】axiosPromise based HTTP client for the browser and node.js项目地址: https://gitcode.com/GitHub_Trending/ax/axiosaxios.create()是 axios 中“一次配置、处处生效”的核心入口它让你基于任意一份完整的请求配置创建一个预配置的实例该实例与默认axios对象共享同一套请求/响应 API却拥有独立的defaults和拦截器栈。读完本文你将掌握按服务划分实例的组织方式、配置在“库默认 → 实例默认 → 请求参数”三层之间的合并与覆盖规则并能通过 lib/axios.js 等源码验证上述每一条行为。一、基本用法创建一个预配置实例文档 docs/fr/pages/advanced/create-an-instance.md 给出的最简示例如下import axios from axios; const instance axios.create({ baseURL: https://api.example.com, timeout: 5000, headers: { X-Custom-Header: foobar }, });创建之后实例的用法与默认axios对象完全一致const response await instance.get(/users/1);这里的关键事实是create方法接受完整的请求配置对象baseURL、timeout、headers、adapter、validateStatus等均可传入。也就是说实例本质上就是“一份固化的请求配置基线 完整的请求 API”。从源码看这个“基线”在构造 Axios 类 时被直接保存为实例属性class Axios { constructor(instanceConfig) { this.defaults instanceConfig || {}; this.interceptors { request: new InterceptorManager(), response: new InterceptorManager(), }; } }注意两点见 lib/core/Axios.jsdefaults直接引用你传入的配置对象因此创建后对instance.defaults的写入会立即影响后续请求详见第四节每个实例在构造时都会新建两个InterceptorManager这是“实例间拦截器相互隔离”的直接来源。二、为什么要用实例四个典型场景对于超过单文件的任何应用文档都推荐通过实例组织请求。以下四个场景均直接继承自文档原文。2.1 按服务划分 baseURL大多数应用会同时访问多个 API。为每个服务创建一个独立实例可以避免在每次调用中重复书写基址const githubApi axios.create({ baseURL: https://api.github.com }); const internalApi axios.create({ baseURL: https://api.internal.example.com }); const { data: repos } await githubApi.get(/users/axios/repos); const { data: users } await internalApi.get(/users);baseURL的拼接由 buildFullPath 完成当请求url不是绝对 URL 时才前缀baseURL。需要注意官方文档的提醒baseURL是 URL 构造的便利工具不是安全边界如果url来自不可信输入应先自行校验见 request-config 文档 对allowAbsoluteUrls的说明。2.2 共享认证头把认证 token 挂到某一个实例上即可让该实例发出的每个请求都自动携带而不会污染其他实例const authApi axios.create({ baseURL: https://api.example.com, headers: { Authorization: Bearer ${getToken()}, }, });这一点与全局默认值的风险形成鲜明对比config-defaults 文档 明确警告如果把 token 写到axios.defaults.headers.common[Authorization]该 token 会被发给所有域名包括你并不掌控的第三方 API。实例化正是隔离凭据泄露范围的标准做法。2.3 按服务设置超时与重试不同服务的可靠性特征不同实时服务可以设置紧凑的超时批处理任务则可以放宽。文档示例const realtimeApi axios.create({ baseURL: https://realtime.example.com, timeout: 2000 }); const batchApi axios.create({ baseURL: https://batch.example.com, timeout: 60000 });对照 lib/defaults/index.js 可以看到库级别的默认timeout为0即“不创建超时”。因此只有当实例或请求显式设置timeout毫秒数时超时才会生效请求耗时超过timeout时请求会被中止。2.4 相互隔离的拦截器添加到某个实例上的拦截器只对该实例生效天然实现了关注点分离const loggingApi axios.create({ baseURL: https://api.example.com }); loggingApi.interceptors.request.use((config) { console.log(→ ${config.method?.toUpperCase()} ${config.url}); return config; });从源码看隔离性来自请求分发链路Axios._request 组装拦截器链时遍历的是this.interceptors.request/this.interceptors.response而this正是发起请求的那个实例对象。每个实例持有独立的 InterceptorManager其use()方法把fulfilled/rejected处理器连同synchronous、runWhen选项压入本实例的handlers栈并通过返回的id支持eject(id)精确移除。因此loggingApi上的日志拦截器永远不会出现在githubApi的调用链里。三、请求时覆盖实例默认值在请求时传入的配置始终覆盖实例的默认值const api axios.create({ timeout: 5000 }); // 该特定请求改为使用 30 秒超时 await api.get(/slow-endpoint, { timeout: 30000 });这背后是明确的三层优先级顺序与 config-defaults 文档 中 “Config order of precedence” 一节一致库默认值lib/defaults/index.jstimeout: 0、adapter: [xhr, http, fetch]、validateStatus仅接受 200–299、headers.common.Accept: application/json, text/plain, */*等实例默认值axios.create(config)传入的配置请求级配置每次调用传入的配置优先级最高。合并发生在 Axios._request 的第一行有效逻辑config mergeConfig(this.defaults, config);四、mergeConfig合并规则的源码级剖析lib/core/mergeConfig.js 并不对所有字段做简单深合并而是通过一张mergeMap第 118–150 行为不同字段指定不同策略策略字段语义valueFromConfig2url、method、data只取请求级配置不继承实例默认值defaultToConfig2baseURL、timeout、adapter、responseType、transformRequest/Response、paramsSerializer、withCredentials、httpAgent/httpsAgent等请求级优先缺省回退实例默认值mergeDeepProperties大小写不敏感headers两方头信息按 key 深度合并未列出的字段其余任意配置项默认深合并这张表解释了几条文档行为data是请求专属的它使用valueFromConfig2axios 不会把请求体从全局或实例默认值中继承或深合并。如果每个请求都需要共享的 body 字段应通过请求拦截器或transformRequest注入request-config 文档 的完整配置示例中也有相同注释。headers的大小写不敏感合并实例上写Authorization、请求上写authorization也能正确覆盖因为 headers 合并路径传入了caseless: true第 48–57 行。此外还有一个值得注意的安全细节mergeConfig使用Object.create(null)构造结果对象并显式恢复非枚举的hasOwnProperty目的是防止被污染的Object.prototype键如toString通过原型链注入配置——tests/unit/prototypePollution.test.js中有大量用例验证这一防护在实例场景下同样生效。五、createInstance实例是如何组装出来的回到入口函数 createInstancelib/axios.jsfunction createInstance(defaultConfig) { const context new Axios(defaultConfig); const instance bind(Axios.prototype.request, context); // Copy axios.prototype to instance utils.extend(instance, Axios.prototype, context, { allOwnKeys: true }); // Copy context to instance utils.extend(instance, context, null, { allOwnKeys: true }); // Factory for creating new instances instance.create function create(instanceConfig) { return createInstance(mergeConfig(defaultConfig, instanceConfig)); }; return instance; }四个步骤各有一层含义new Axios(defaultConfig)把传入配置固化为context.defaults并创建专属拦截器栈bind(Axios.prototype.request, context)导出对象的“主调用入口”instance(configOrUrl, config)就是绑定了该上下文的request方法因此instance(/users)与instance.get(/users)走同一条分发链路两次utils.extend先把Axios.prototype上的get/post/put/patch/delete/head/options/query及*Form别名在 lib/core/Axios.js 中批量生成、getUri等方法拷到实例上再拷入实例自身的defaults与interceptors从而形成文档所说的“与默认 axios 对象共享同一 API”实例工厂可以嵌套instance.create(instanceConfig)会用mergeConfig(defaultConfig, instanceConfig)把“父实例默认值 新增配置”合并后再生成新实例。这意味着你可以从已有实例派生出只多改一两个字段如不同timeout的子客户端而无需重写整份配置。默认导出的全局axios对象本身也是同一工厂的产物lib/axios.jsconst axios createInstance(defaults)——全局对象与自定义实例在结构上完全同构差别只在默认配置来源。六、创建之后修改默认值instance.defaults文档最后一条提示实例创建后仍可通过写入instance.defaults修改默认值instance.defaults.headers.common[Authorization] Bearer ${newToken};因为 Axios 构造函数 中this.defaults直接持有创建时传入的对象而每次请求都会执行mergeConfig(this.defaults, config)实时读取它所以对defaults的任何后续写入改timeout、更新 token、增删headers都会从下一次请求开始生效——这对“token 轮换后刷新全局认证头”这类场景非常实用且影响范围严格限定在该实例内。config-defaults 文档 中的实例默认值示例与本文完全对应var instance axios.create({ baseURL: https://jsonplaceholder.typicode.com/posts, timeout: 1000, headers: { Authorization: foobar }, }); instance.defaults.headers.common[Authorization] AUTH_TOKEN;七、小结axios.create(config)接受完整的请求配置返回一个defaults与拦截器栈均独立的实例请求 API 与全局axios完全一致典型组织方式按服务拆分baseURL、按凭据隔离Authorization头、按可靠性设定timeout、按职责挂载独立拦截器配置合并遵循“库默认 → 实例默认 → 请求配置”三层优先级其中data等特殊字段只取请求级值源码依据mergeConfig 的策略表instance.defaults可在运行时修改并立即作用于后续请求instance.create()支持从现有实例派生新实例相关测试可在 tests/unit/api.test.js、tests/unit/core/mergeConfig.test.js 与 tests/unit/prototypePollution.test.js 中查证。【免费下载链接】axiosPromise based HTTP client for the browser and node.js项目地址: https://gitcode.com/GitHub_Trending/ax/axios创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表