Skip to content

Axios 安装模式

适用场景:项目使用 Axios,可一键接入(推荐)。

基本接入

javascript
import axios from 'axios';
import {
  setupRequestGuard,        // setup 安装方法
  ConsoleRequestGuardLogger // 内置的日志类(也可继承 RequestGuardLogger 实现)
} from '@hydd/request-guard';

// setupRequestGuard(axios, options) → 返回 RequestGuardController
const requestManager = setupRequestGuard(axios, {
  // 消息提示出口
  notify: (payload) => Toast.show(payload.message),
  // 日志观测
  logger: new ConsoleRequestGuardLogger({ devOnly: true }),
  // 全局规则
  rules: [{ method: 'post', duplicate: true }]
});

requestManagerRequestGuardController,可以调用:

  • configure(options) — 更新全局配置
  • setRules(rules) — 覆盖全局规则
  • addRule(rule) — 追加一条规则
  • clearRules() — 清空所有规则
  • clearState() — 清空所有能力状态
  • getStateSnapshot() — 获取当前状态快照
  • createLoadingKey() — 创建可复用的 loadingKey
  • isLoading(key) — 查询某个 key 是否仍在执行中
  • subscribeLoading() — 订阅某个 key 的 loading 布尔变化
  • uninstall() — 卸载守护,恢复 axios 原始行为
  • circuitBreaker — 熔断器手动控制 API

完整方法说明见 RequestGuardController

版本适配与覆盖面

覆盖面与 axios 版本和调用形式有关。本节帮你确认:你的版本和用法下,哪些请求受守护。

基本接入姿势

方式一:传入 axios,统一治理

javascript
import axios from 'axios';
import { setupRequestGuard } from '@hydd/request-guard';

// 在 axios.create 之前进行注册
setupRequestGuard(axios);

const service = axios.create({ baseURL: '/api' });

接入后 create() 的实例都受守护。适合在应用入口统一接管。

方式二:传入单个实例,只守护该实例

javascript
const service = axios.create({ baseURL: '/api' });

setupRequestGuard(service);

同副本内其他实例不受影响。适合只治理某个已知客户端。

版本表现

常用版本0.x / 1.0 – 1.1 / ≥ 1.5.0):按上面姿势走即可。

  • ⚠️ ≥ 1.5.0 下,若用 service(config) 这种可调用直调形态,需补一个 source
javascript
setupRequestGuard(service, {
  axios: { source: axios }   // 让 service(config) 也受守护
});

特殊版本1.2.0 – 1.4.x):只有传入对象的命名方法axios.post / service.post)会正常守护,其他调用形式(可调用直调 service(config)、之后 create() 的派生实例)会默默失效。

解决方案是开启 forceGuard

javascript
setupRequestGuard(service, {
  axios: { source: axios, forceGuard: true }
});

forceGuard 的代价

开启后守护会扩大到该 axios 副本内所有实例(含第三方 SDK 使用同一副本时的请求),会牺牲实例隔离

多份 axios 模块

如果项目里存在多份 axios 模块(monorepo 依赖重复 / 第三方 SDK 内置 axios),需要每份各自接入——守护装在 A 副本上,B 副本的请求不受守护,也没有运行期信号。

兼容性经 29 个 axios 版本验证:0.27.2 → 1.19.0

覆盖面速查表

接入方式0.x / 1.0 – 1.11.2.0 – 1.4.x≥ 1.5.0
传 axios(统一治理)✅ 全部调用形式⚠️ 仅命名方法(axios.post 等)✅ 全部调用形式
传单个实例✅ 该实例全部调用形式⚠️ 仅命名方法(service.post 等)⚠️ 命名方法受守护;service(config) 直调需补 axios.source

表中“全部调用形式”指命名方法(get / post / …)与可调用直调(axios(config) / service(config))。接入前已创建的实例不受守护(见下方注意事项 ①)。

接入注意事项

  1. 接入顺序:传 axios 默认导出时,接入必须先于 axios.create()——接入前已创建的实例不受守护,且没有运行期信号提示。
  2. 多份 axios 模块:守护装在 A 副本,B 副本(monorepo 依赖重复 / 第三方 SDK 内置)不受守护,无信号。每份各自接入。
  3. 版本缺口:见上文“版本表现”。

axios 选项配置参考

字段类型默认说明
axios.sourceaxios 模块对象让“传实例 + 可调用直调”受守护;必须是创建该实例的同一份 axios 模块
axios.forceGuardbooleanfalse覆盖 1.2.0 – 1.4.x 特殊版本下失效的调用形式;开启后作用于整个 axios 副本,会牺牲实例隔离

axios: { source, forceGuard } 仅在 Axios 安装模式可用。

与外部按钮 loading 协作

如果你希望按钮、局部骨架屏、弹窗提交态等 UI 直接复用 guard 的执行态,可以使用 loadingKey(完整语义、并发计数与框架示例见 Loading 协作 API):

javascript
import axios from 'axios';
import {
  createLoadingKey,
  isLoading,
  setupRequestGuard,
  subscribeLoading
} from '@hydd/request-guard';

setupRequestGuard(axios, {
  rules: [{ method: 'post', duplicate: true }]
});

const submitLoadingKey = createLoadingKey('submit-order');
const unsubscribe = subscribeLoading(submitLoadingKey, (loading) => {
  console.log('submit button loading:', loading);
});

await axios.post('/api/order/submit', { orderId: '12345' }, {
  requestGuard: {
    duplicate: true,
    loadingKey: submitLoadingKey
  }
});

console.log(isLoading(submitLoadingKey)); // false
unsubscribe();

如果项目依赖精准区分实例、希望跨版本行为完全一致,或命中上述注意事项且无法调整,可以考虑 Wrapper 模式——它不依赖 axios 版本相关的行为。

基于 MIT 许可发布