HarmonyOS 7 互动卡片重复提交:两个入口同时点击,服务端怎样识别同一次动作

HarmonyOS 7 互动卡片重复提交:两个入口同时点击,服务端怎样识别同一次动作

页面按钮禁用只能约束一个界面。卡片和应用页同时发起同一个动作时,各自的防抖状态互不相通。需要把操作身份带到结果保存的位置,而不是只在界面保存一个loading变量。

适配范围

这里的回执表只演示同步单进程行为,不是可直接部署的服务端。生产需要唯一索引、事务和持久化;异步副作用或崩溃窗口必须另行处理。JSON指纹要求字段顺序固定,正式协议应明确规范序列化。

案例一

卡片与应用页使用同一个操作标识:两次提交返回同一回执,副作用只执行一次。

案例二

错误复用了操作标识:相同key却携带不同item,必须冲突报错,不能返回上一次操作的成功回执。

可以运行的实现

export class ReceiptStore {
  receipts = new Map();
  submit(key, payload, perform) {
    const fingerprint = JSON.stringify(payload);
    const old = this.receipts.get(key);
    if (old) {
      if (old.fingerprint !== fingerprint) throw Error('key_payload_conflict');
      return old.result;
    }
    const result = perform(payload);
    this.receipts.set(key, {fingerprint, result});
    return result;
  }
}

复现与断言

把实现与以下测试放进同一个example.mjs,执行node example.mjs。断言失败会报错,全部通过正常退出。这些断言已经在本地Node.js执行;它们不代表SDK编译、真机接口调用或性能实测已经通过。

import assert from 'node:assert/strict';
let calls = 0;
const service = new ReceiptStore();
const action = {item:'A',count:1};
const perform = () => ({receipt:++calls});
assert.equal(service.submit('operation-1',action,perform).receipt, 1);
assert.equal(service.submit('operation-1',action,perform).receipt, 1);
assert.equal(calls, 1);
assert.throws(() => service.submit('operation-1',{item:'B',count:1},perform));
assert.equal(service.submit('operation-2',action,perform).receipt, 2);

方案取舍

界面防抖改善体验,但不提供跨入口幂等。操作key与参数指纹组合能发现重复与误复用;单纯按参数去重会误伤两次合法的相同操作。

接入时别漏掉这些边界

这里的回执表只演示同步单进程行为,不是可直接部署的服务端。生产需要唯一索引、事务和持久化;异步副作用或崩溃窗口必须另行处理。JSON指纹要求字段顺序固定,正式协议应明确规范序列化。

复用时把输入获取与纯逻辑分开:界面、系统事件和服务请求负责取得真实输入,独立模块负责给出判断或保存状态。保留上述两个案例作为回归测试,并对失败原因记录最少必要日志,不记录文件内容、账号凭据或其它敏感数据。升级SDK后重新核对支持设备、接口版本与错误行为,而不是只改目标版本号。

官方资料

HarmonyOS 官方能力入口

示例验证环境为Node.js,验证范围是应用侧逻辑。本文不将示例当作系统接口接入代码;具体接口的支持设备、最低版本和调用方式,以所用SDK对应的官方文档为准。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐