Skip to content

业务场景方案指南

本章来自一个真实中后台项目(100+ API 模块、700+ 接口、Vue 2 + qiankun 微前端)的完整治理复盘:从"全量守护"走到"请求级显式声明",中间踩过的坑与最终形成的决策规则,全部沉淀在这里。你可以把它当作接入方案评审时的对照清单。

一、守护范围怎么圈:全量 rules 还是请求级声明?

两种模式都受支持,选择取决于项目形态:

维度全量 rules(方法级兜底)请求级显式声明
适合项目新项目 / 接口数量少 / 调用点风格统一大型存量项目 / 查询大量使用 POST
心智负担全员必须了解守护机制,否则"正常代码"也可能被拦不知道机制的人最多"没防重",不会踩坑
故障模式误拦查询类请求 → 交互静默无响应漏声明 → 回到接入前原状,业务 loading 兜底
守护范围可见性需读全局配置推导grep requestGuard: 一眼可见,代码即文档

经验结论:存量大项目建议声明制——移除全局 rules,只在需要防重的接口显式传 requestGuard: { duplicate: true },策略与提示文案放 defaults 统一继承。

js
// 安装点:defaults 只放继承项,不配 rules
setupRequestGuard(service, {
  defaults: {
    duplicate: { strategy: 'ignore', message: '请求处理中,请勿重复操作' }
  }
});

// api 层:需要防重的接口加一行
export const auditSubmit = (params) =>
  request({ url: '/inspectionApproval/auditSubmit', method: 'POST', data: params,
    requestGuard: { duplicate: true } });

别用 URL 正则圈范围

我们实测该项目 756 个接口中约 12% 命名无规律(terminateurgehandlediscardsyncToVideoPlatform……),同时查询接口大量携带变更类关键字(getAuditRecordListmyPage)。URL 正则会漏判误判并存——关键字机扫只能当"候选提示",最终逐条人工判读。

二、接口分类决策表

按"重复提交的业务危害"给接口分类,再决定是否声明防重:

分类典型接口建议
审批 / 提交submit、audit、approve、confirm、sign✅ 声明,最高优先
流程流转 / 关闭handle、transfer、close、terminate✅ 声明
任务操作urge、stop、cancel、enable/disable✅ 声明
推送 / 消息push、send、resend✅ 声明(重复触发会打扰真实用户)
同步 / 生成 / 批量sync、generate、refresh、batchXxx✅ 声明(重复触发 = 重复重任务)
文件上传 / 导入upload、import(FormData 传参)⚠️ 默认不推荐,见下节
查询类 POSTpage、list、query、search❌ 不要用 ignore,见第四节

两条配套规则:

  1. 同端点一致性:同一 URL 在多个 api 模块重复封装时,必须同批全部声明或全部不声明,避免同一接口两处行为不一致
  2. 命名欺骗校验:声明前看函数实现和调用方语义,别信 URL——我们遇到过 LoadingOrganization 实为分页查询的案例

三、文件上传:默认不推荐接入防重

这是我们复盘中最重要的一条结论。

为什么不推荐

  • 中后台项目的上传端点高度收敛(多个业务共用同一个文件中心接口),同 URL 是常态
  • FormData 的文件内容默认不参与判重,两次"看起来一样"的上传请求可能携带完全不同的文件
  • 两者叠加,"连拍多图并发上传""多业务同时上传"这类正常操作存在被误判为重复请求的风险;在 ignore 策略下表现为第二个上传静默无响应,用户与开发都很难定位

我们的处理:上传/导入类接口全部不声明防重,"防止用户重复点上传按钮"交给按钮层解决(GuardButton 的 loading + disabled 联动天然覆盖)。

如果业务确实要求上传防重(例如防止同一文件重复导入):使用公开配置项 formDataResolver 让文件的身份特征(如 name/size/lastModified)参与判重,并对"程序生成的文件对象""同名不同内容"等边界做充分测试后再上线。配置方式见 防重复请求

四、查询类 POST:不要用 ignore

很多中后台项目的查询也走 POST。如果对它们套用 ignore 防重,以下四类正常代码都会中招——重复请求返回的 Promise 永远 pending,then/catch/finally 都不执行(这是 ignore 的公开语义,详见 防重复请求):

场景表现
同一自取数组件在同页多实例(如两个相同的模板选择器同时挂载即请求)后发实例永远拿不到数据
远程搜索快速重入(输入 A → AB → 删回 A,首个请求未落地)loading 永转、选项空白
级联/树组件懒加载,同节点快速重复展开节点永久转圈
多组件并发 await 同参的共享请求(如 store action 被父子组件同时 dispatch)第二个调用方的 async 流程永久挂起

建议

  • 查询类接口默认不声明防重
  • 确有"合并相同并发查询"需求时,按 URL 定向使用 strategy: 'reuse'(重复请求共享首个结果、正常 settle,不会挂起调用方)——语义与查询天然匹配

五、上线前的验证清单

方案定了不等于结束,我们建议至少做三层验证:

  1. 黑盒行为验证:用 mock adapter 对"声明的接口拦不拦、未声明的接口放不放、不同参并发放不放、串行重复放不放"做自动化断言,以实际安装版本的行为为准,不要凭文档记忆
  2. 正向双击测试:对每类代表接口在真实页面双击提交,DevTools Network 中目标请求只应发出 1 次,且有 toast 反馈(弱网节流更易复现)
  3. 反向回归:第四节列出的四类场景必须完全正常——这是"守护范围没有泄漏"的证据

相关章节

基于 MIT 许可发布