【JitWeb】openLoading 后无异步 await 时,Loading 与按钮动画不生效

摘要

page.ts 事件 handler 中,若 FeedBack.openLoading()closeLoading() 之间没有真实异步 await,会出现两类问题:

  1. Loading 遮罩与按钮点击动画完全不生效(不是播得太短,而是整段反馈缺失)。
  2. 用户快速连点时,handler 会被多次执行,导致重复 append、重复汇总等业务副作用。

在中间插入任意真实 await(如无关的 model.get)后,Loading 正常显示、连点问题随之缓解——说明根因在平台反馈/遮罩机制,而非业务逻辑本身。


出现条件

同时满足以下情况时复现:

# 条件
1 subscribeEventasync handler 内调用 FeedBack.openLoading()
2 openLoadingcloseLoading 之间无真实异步等待(仅同步 append、字段赋值、Modal.close(),或 await 的函数体内无 I/O)
3 Handler 在同一轮事件循环内很快结束并调用 closeLoading()

不出现的情况:中间存在真实异步,例如 await Table5.call(...)await model.get(...)await service.*(...)


现象

1. 视觉反馈完全缺失

  • 全局 Loading 不显示
  • 按钮点击动画 不播放
  • 用户感知为「点了没反应」

2. 快速连点导致逻辑重复执行

因 Loading 未真正挂载/遮罩未生效,按钮在 handler 执行期间仍可继续点击。用户连点或误以为未响应再次点击时,同一事件会并发或连续触发多次,例如:

  • 子表 fe12 重复 append 相同明细
  • totalAmountOfVolume() 重复汇总(数值被放大)
  • 弹窗可能多次 close()(表现不稳定)

这与「有 Loading 正常工作时」的用户体验形成鲜明对比:Loading 生效时,遮罩会阻断二次操作。


复现案例

元素workflows.listOfDocumentsApproval
页面workflows/listOfDocumentsApproval/pages/NodePage/page.ts
事件Table5clickDtKjbS(库存明细弹窗确认添加)

问题写法(去掉 workaround 后):

this.Table5.subscribeEvent("clickDtKjbS", async () => {
    this.app.modules.FeedBack.openLoading("正在添加出库明细...");

    this.approveForm.formData.fe12.append(/* convertRowList 同步追加 */);

    await this.totalAmountOfVolume(); // 无真实 I/O
    this.Modal4.close();
    this.app.modules.FeedBack.closeLoading();
});

步骤

  1. 打开出库单审批 → 子表 → 库存明细弹窗。
  2. 勾选行,快速连点确认按钮 2~3 次。
  3. 观察子表:同一批明细可能被重复添加;全程无 Loading、无按钮动画。

对照(插入无关 await get 后):

const RowData1 = Jit.datatypes.RowData(
    await this.app.models.salesOrders.get(null, null, 2),
    { "generic": "models.salesOrders", "title": "单行数据1" }
);
  • Loading 与按钮动画正常

同页正常对照clickrAXhdb 中间有 await this.Table5.call(...),无上述问题。


预期 vs 实际

预期 实际(问题路径)
Loading openLoading() 后立即显示遮罩 完全不显示
按钮反馈 点击有动画 完全不播放
防重复 Loading 期间按钮应被遮罩/禁用 可继续点击,逻辑多次执行
数据 一次点击只追加一批明细 连点可重复 append

业务影响

  • 出库明细可能被重复添加,汇总金额/数量错误。
  • 用户因无反馈而反复点击,放大问题。
  • 业务被迫写无意义的 model.get 作为 workaround,增加维护成本与无效请求。

根因推测(供平台排查)

FeedBack.openLoading() 可能仅更新状态,未让出渲染、未挂载遮罩;handler 同步结束后立刻 closeLoading(),UI 来不及绘制。遮罩未生效时,无法拦截连点,导致 handler 重复进入。


建议修复

  1. openLoading 内部:状态更新后保证至少一次渲染让出(nextTick / rAF),并同步挂载可拦截操作的遮罩
  2. 事件层:对 Table/按钮在 handler 执行期间提供防重复触发(与 Loading 状态绑定)。
  3. 文档:在 open-close-loading pattern 中说明:纯同步逻辑下 Loading 不生效,且存在重复执行风险

当前 workaround(临时)

openLoadingcloseLoading 之间保留一次真实 await(如无关 salesOrders.get),借异步间隙让 Loading 显示并阻断连点。