axios 需要配多个 baseURL 怎么处理?用错场景反而更麻烦

编程狮(w3cschool.cn) 2026-10-24 07:01:59 浏览数 (32)
反馈

先给结论:axios 里要对接多套后端,别在一个实例上反复改接口基地址,正确做法是按后端拆出多个 axios 实例,每个实例各自持有自己的接口基地址;只有临时切一次的场景才用请求拦截器动态改写。

axios 要配多个baseURL 怎么办?

新手最容易踩的坑是"改完再发":请求发出前把实例上的基地址改掉,结果并发请求互相覆盖,A 请求用上了 B 的地址,排查起来毫无规律。

本文给出三种写法并说明各自适合什么场景,重点讲清哪些情况不该动基地址。示例基于常见的请求库用法,版本差异会在边界一节说明。

先看结论

  • 多套后端就拆多个实例:每个实例持有自己的接口基地址,互不干扰。
  • 动态改写只适合少量例外:写进请求拦截器,用前缀判断走哪套后端。
  • 别在请求前临时改接口基地址:实例是共享对象,并发场景下一定会互相覆盖。

一、最小场景:两套后端同时存在

把问题定死:页面要同时请求业务接口和文件服务,两个接口域名不一样,但都要带同一套鉴权头。两套后端意味着两个接口基地址,怎么放这两个值就是这里要解决的问题。

第一种写法是按后端拆 axios 实例:

import axios from 'axios';

const api = axios.create({ baseURL: 'https://api.example.com' });
const file = axios.create({ baseURL: 'https://file.example.com' });

api.interceptors.request.use((config) => {
  config.headers.Authorization = localStorage.getItem('token');
  return config;
});

export { api, file };

这段做的是建两个各自持有基地址的实例,鉴权只在业务实例上加。预期结果(未在本机执行):两个实例发出的请求分别指向各自的域名,互不影响。

第二种写法是不设基地址,在拦截器里按前缀决定:

const service = axios.create();

service.interceptors.request.use((config) => {
  if (config.url.startsWith('/file')) {
    config.baseURL = 'https://file.example.com';
  } else {
    config.baseURL = 'https://api.example.com';
  }
  return config;
});

这段做的是每次请求前按路径前缀挑一个基地址。它只在拦截器里改当次的配置对象,不会污染实例本身,这一点和直接改实例属性有本质区别。

请求相关的细节记不清时,AJAX 教程 里的示例可以直接对照。

二、什么场景该用哪种

接口基地址放在哪里,取决于两套后端要并存多久,按这个标准选基本不会错。

2.1 长期并存的两套后端用多实例

业务接口、文件服务、第三方开放接口,只要长期并存,就各自建一个实例。好处是基地址、超时、鉴权可以分别配置,出问题时定位也快。

2.2 少量例外用拦截器改写

只有个别接口走另一套后端时,为它单独建实例反而显得啰嗦。这时候用前缀判断,在拦截器里挑基地址更轻。

2.3 多环境切换交给环境变量

开发、测试、生产对应不同的域名,这类切换不要写死在代码里,交给环境变量在打包时决定。

三种处理多基地址的写法适用场景

三、用错场景反而更麻烦的地方

3.1 在请求前临时改实例属性

这是最典型的错误写法。接口基地址被临时改成另一个域名后,实例是共享对象,改它的属性会影响所有正在排队的请求,并发一上来就乱。

判断标准很直接:凡是出现"先改后发再改回来"的写法,都该换成多实例。

3.2 把域名写进每一个请求

把完整域名散落在各个请求定义里,换环境时要全局替换,漏一处就是线上事故。

3.3 忽略超时与重试的差异

不同后端的响应特征不一样,文件服务通常需要更长的超时。多实例的写法正好可以分别设置,这也是它优于统一改写的地方。

写法细节可以对照 JavaScript 教程 里的对象与函数章节确认。

3.4 模块导出的实例是单例

把实例集中在一个文件导出时,这个文件只会被加载一次,导出的实例在进程里是同一个对象。这本来是好事,但如果你图方便在实例上挂了"当前用户"之类的状态,并发请求就会互相读到对方的数据。实例只适合放配置和拦截器,请求级别的状态必须放在每次调用里。

四、验证清单

4.1 逐个域名称看网络面板

确认每个请求的地址前缀正确,尤其是并发触发的那几个。

4.2 鉴权头有没有带错

多实例时拦截器可能只挂在其中一个上,另一个实例的请求会缺少鉴权头。

4.3 换环境后重新打包验证

环境变量改完必须重启或重新打包,否则读到的还是旧值。

4.4 验证清单

  • 检查:确认每个实例持有各自的接口基地址
  • 运行:同时触发两个域名的请求,观察网络面板
  • 预期:地址前缀各自正确,鉴权头按预期带上
  • 失败:地址串到别的域名,说明有人在改实例属性
  • 修复:把临时改属性的写法换成独立实例
  • 验证:连续并发十次,结果始终一致才算通过

并发请求下共享实例被覆盖的时序

总结

多套后端并存的场景,按后端拆实例是最省心的一档;拦截器改写适合少量例外;环境差异交给环境变量。真正要避免的是在共享实例上临时改基地址。

三条要点带走:

  • 接口基地址是实例级的配置,不要在一次请求里改来改去;
  • 拦截器改的是当次配置对象,改实例属性则会污染所有排队请求;
  • 域名不要散落在请求定义里,统一交给常量或环境变量。

下一步建议把实例集中在一个文件里导出,并给每个实例单独配置超时。属性细节可以对照 AJAX 速查手册 再核一遍。

常见问题

Q:能不能完全不设接口基地址?

A:可以,每个请求写完整地址。代价是换环境时要全局替换,域名一多就很难维护。

Q:并发请求为什么会串到别的域名?

A:因为改的是共享实例上的属性。改成按后端拆实例,或者在拦截器里改当次的配置对象。

Q:多个实例会不会增加体积?

A:几乎不会。实例本身只是配置对象,真正占体积的是请求库本身,只会被打包一次。

Q:环境切换用环境变量还是配置文件?

A:优先用环境变量,打包时按环境取值,一套代码可以对付多套后端,不需要为每个环境改代码。

Q:不同后端要不同的超时怎么办?

A:这正适合多实例。每个实例单独设置超时与重试,比在拦截器里判断更清晰。

延伸学习

想把这个知识点补扎实,可以按这个顺序来:

  1. 想把语言基础补系统,JavaScript 原生模块 可以跟一遍;
  2. 读一篇相关笔记 用 Ajax 请求服务器数据,看别人踩过的坑;
  3. 想随手验证一段代码,用 JavaScript 在线运行 跑一遍最快。

0 人点赞