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。适合"一个动作可能触发多个请求"的场景。 - 受请求级总开关约束。
loadingKey从config.requestGuard.loadingKey读取。如果该请求requestGuard: false,loading 协作会一并失效(守护层不会绕过请求的显式选择)。 - key 的唯一性是运行期级。
createLoadingKey生成的 key 只保证在当前 manager 运行期内唯一;不要把它 持久化或跨运行期复用。 - 监听器异常被隔离。
listener内部抛错不会中断请求执行,错误会走内部错误处理(phase: loading:listener)。
按需入口与小程序
这三个函数在按需入口 @hydd/request-guard/core 下同样导出,小程序等场景从 core 引入即可,用法一致。
与控制器方法的关系
包根导出的 createLoadingKey / isLoading / subscribeLoading 与 setupRequestGuard(...) 返回控制器上的同名方法行为一致,作用于同一份运行期状态,按习惯任选其一即可。 另外 clearState() 会清空所有能力状态(包含 loading 计数与等待方),常用于登出、 路由切换时复位。
相关链接
- 请求级如何声明
loadingKey:见 请求级配置 - 控制器完整方法表:见 RequestGuardController

