Skip to content

Loading 协作 API

request-guard 把"受守护请求的执行态"通过一个公共标识(loadingKey)暴露给外部 UI,让按钮、对话框、 局部骨架等可以跟随请求的真实执行生命周期,而不必在业务里另写一套 loading 标志位。

围绕这个能力有三个公开函数:

函数签名作用
createLoadingKey(label?)(label?: string) => string创建一个当前运行期内唯一的 loadingKey
subscribeLoading(key, listener)(key: string, listener: (loading: boolean) => void) => () => void订阅某个 key 的执行态变化,返回取消订阅函数
isLoading(key)(key: string) => boolean同步查询某个 key 当前是否处于执行中

它们既是包根的独立导出,也是 setupRequestGuard(...) 返回的控制器方法(见 RequestGuardController)。

为什么需要它

手写 loading 标志位常见的坑:

  • try/finally 里忘了复位,请求异常后按钮一直转
  • 重试期间标志位提前变 false,用户以为结束了又点一次
  • 同一个动作被多处触发,计数错乱,loading 闪烁

loadingKey 把这些都交给守护层统一管理:它的计数覆盖整个执行生命周期(包含重试等待、响应收尾、 finally),并对并发做引用计数,业务侧只需要订阅一个布尔值。

用法

让按钮的 loading 跟随这次请求的真实执行态,不用自己维护标志位、也不怕重试/异常时忘了复位。

Vue 3

js
const loading = ref(false);
const submitKey = createLoadingKey('submit-order');

// 请求开始 loading=true,结束(含重试、报错)自动 false
subscribeLoading(submitKey, (v) => (loading.value = v));

// 发请求时带上 loadingKey
http.post('/api/order/submit', data, { requestGuard: { loadingKey: submitKey } });

React

js
const [loading, setLoading] = useState(false);
const submitKey = useRef(createLoadingKey('submit-order')).current;

// 请求开始 loading=true,结束(含重试、报错)自动 false
useEffect(() => subscribeLoading(submitKey, setLoading), []);

// 发请求时带上 loadingKey
http.post('/api/order/submit', data, { requestGuard: { loadingKey: submitKey } });

需要时也可以用 isLoading(submitKey) 在任意位置同步查询当前是否在执行中。

行为细节

理解下面几条语义可以避免踩坑:

  • 订阅即回调一次。 subscribeLoading(key, listener) 在订阅的瞬间会用当前状态同步回调一次 listener, 之后只在 false ↔ true 边沿变化时再回调。你不需要在订阅后再手动读一次初始值。
  • 覆盖完整生命周期。 计数从请求开始一直保持到执行结束,包含 retry 的等待间隔与响应收尾阶段,所以 重试期间 isLoading 仍为 true
  • 并发引用计数。 多个并发请求绑定同一个 loadingKey 时,计数累加;只有全部结束后才会变回 false。适合"一个动作可能触发多个请求"的场景。
  • 受请求级总开关约束。 loadingKeyconfig.requestGuard.loadingKey 读取。如果该请求 requestGuard: false,loading 协作会一并失效(守护层不会绕过请求的显式选择)。
  • key 的唯一性是运行期级。 createLoadingKey 生成的 key 只保证在当前 manager 运行期内唯一;不要把它 持久化或跨运行期复用。
  • 监听器异常被隔离。 listener 内部抛错不会中断请求执行,错误会走内部错误处理(phase: loading:listener)。

按需入口与小程序

这三个函数在按需入口 @hydd/request-guard/core 下同样导出,小程序等场景从 core 引入即可,用法一致。

与控制器方法的关系

包根导出的 createLoadingKey / isLoading / subscribeLoadingsetupRequestGuard(...) 返回控制器上的同名方法行为一致,作用于同一份运行期状态,按习惯任选其一即可。 另外 clearState() 会清空所有能力状态(包含 loading 计数与等待方),常用于登出、 路由切换时复位。

相关链接

基于 MIT 许可发布