首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【线上缺陷】前端重复提交的产生原因和预防措施

【线上缺陷】前端重复提交的产生原因和预防措施

作者头像
Antony
发布2025-11-12 13:59:19
发布2025-11-12 13:59:19
740
举报

线上缺陷

跟夏天赶蚊子一样,这是一类非常让人头疼和烦恼的问题。业务人员在操作过程中点击提交之后,页面依旧停留在了待提交界面,于是又提交了一次。系统接受了来自前端的提交,并向前端返回了2条“提交成功”的响应,并在数据库中插入了两条待处理的业务记录(内容相同)。由于这个业务同一时间内只能做一次,在后续处理过程中就报错了。

此类问题虽然不会有严重的业务影响,但是此类问题跟打地鼠一样频繁、重复、跨团队地出现,也暴露出了开发、测试团队的不少问题。

打地鼠游戏的玩法与规则 - 棋牌资讯 - 游戏茶苑
打地鼠游戏的玩法与规则 - 棋牌资讯 - 游戏茶苑

问题产生原因

那么为什么会产生预期外的重复提交的问题呢? 可能有用户、系统实现、业务逻辑和测试等几个方面的原因。

一、用户操作层面的无意行为

1. 误触或操作失误

o 用户因手滑、点击过快(如双击代替单击)、对操作反馈不明确而重复点击(例如按钮点击后无 Loading 提示,用户误以为未触发)。

o 移动端或触摸屏设备上,因触控灵敏度问题可能导致一次物理操作被识别为多次点击。

2. 等待焦虑与重复尝试

o 当请求响应缓慢(如网络延迟、后端处理耗时),用户未看到明确的 “提交中” 反馈时,可能会多次点击按钮试图 “确认操作生效”。

o 对操作结果存疑(如表单提交后未跳转 / 无提示),用户可能重复提交以验证是否成功。

二、技术与系统层面的潜在问题

1. 前端状态管理漏洞

o 按钮禁用逻辑未覆盖所有场景(如异步请求发起后未立即禁用按钮,导致短时间内多次触发)。

o 前端状态未正确重置(如请求失败后,“提交中” 状态未解除,或禁用的按钮未恢复,可能迫使用户刷新页面后再次提交,导致重复)。

2. 网络与请求特性

o 网络波动导致请求 “延迟到达”:用户首次提交后因网络延迟未收到响应,再次提交,最终两个请求都被后端接收。

o 重复请求未被拦截:如前端未使用防抖、节流或 Token 机制,导致同一请求被多次发送(尤其在高频操作场景下)。

3. 浏览器或设备特性

o 浏览器后退 / 刷新操作:用户提交后通过后退按钮返回表单页,再次提交相同内容(可能因缓存导致表单数据未清空)。

o 多标签页 / 窗口:在多标签页中打开同一表单页面,分别提交可能导致重复请求(尤其当页面未做跨标签状态同步时)。

三、业务逻辑设计的疏忽

1. 缺乏明确的操作反馈

o 提交后无 Loading 动画、文字提示(如 “提交中,请稍候”)或进度指示,用户无法判断操作状态,进而重复点击。

o 错误提示不清晰(如仅提示 “提交失败” 而不说明原因),用户可能误以为是点击未生效而重试。

2. 未限制高频操作场景

o 部分业务场景(如点赞、评论、快速保存)允许短时间内多次操作,但未做频率限制,可能因用户连续点击导致重复提交。

四、测试人员的疏忽

在事件发生后,测试人员对该问题进行了复盘。当时的测试人员查看了测试设计和用例,发现

1)测试设计涵盖了“前台重复提交”的测试场景

2)测试执行时也执行了该用例

3)执行时报告了两次“提交成功”,测试人员就认为功能正常。然后就没有报告缺陷。

可以看到

1)测试人员对于重复提交等防呆设计类的场景认知是不足的,即使是触发了问题场景,也眼睁睁看着问题从眼前溜了过去。

2)测试过程也是有瑕疵的,测试人员只查看了前台返回的数据,没有看到后台后续人物执行的报错日志。错过了发现问题的另一个机会。

如何规避

在软件防呆设计中,规避前端意外重复点击提交按钮(如表单提交、订单确认等场景)是常见需求,核心目标是防止重复触发请求(如重复提交数据、重复下单),同时保证用户体验。以下是让豆包梳理的几种常用的技术方案(示例代码仅是示例哦,保鲜不保活):

1. 即时禁用按钮(最常用)

点击按钮后立即禁用,阻止后续点击,直到请求完成(成功 / 失败)后再恢复状态。

• 实现方式:

点击事件触发时,通过disabled属性(HTML 按钮)或样式禁用按钮,并可添加加载状态(如 “提交中...”)。

代码语言:javascript
复制
示例代码(JavaScript):
javascript
const submitBtn = document.getElementById('submitBtn');
submitBtn.addEventListener('click', async () => {
  // 点击后立即禁用按钮,防止重复点击
  submitBtn.disabled = true;
  submitBtn.textContent = '提交中...';
  try {
    // 发送请求
    await api.submitData(formData);
    // 成功后可跳转或提示,按钮可保持禁用(如表单一次性提交)
    alert('提交成功');
  } catch (error) {
    // 失败后恢复按钮可用,允许用户重试
    alert('提交失败,请重试');
    submitBtn.disabled = false;
    submitBtn.textContent = '重新提交';
  }
});

• 优点:简单直接,用户能直观感知 “操作中”,减少重复点击冲动。

• 注意:需在请求失败时恢复按钮状态,避免用户无法重试。

2. 添加点击间隔限制(防抖)

通过防抖(debounce)机制,限制短时间内重复点击(如 1 秒内仅允许一次有效点击)。

• 实现方式:

记录上次点击时间,若两次点击间隔小于阈值(如 500ms),则忽略后续点击。

代码语言:javascript
复制
示例代码:
javascript
let lastClickTime = 0;
const clickThreshold = 1000; // 1秒内不允许重复点击
submitBtn.addEventListener('click', async () => {
  const now = Date.now();
  if (now - lastClickTime < clickThreshold) {
    return; // 忽略重复点击
  }
  lastClickTime = now;
  // 执行提交逻辑...
});

• 适用场景:不希望完全禁用按钮(如高频操作但需限制频率),但可能存在漏判(如请求未完成时用户再次点击)。

3. 前端生成唯一标识(Token)

结合后端校验,确保同一操作仅被处理一次(从根源防止重复提交)。

代码语言:javascript
复制
•	流程:
1.	页面加载时,前端从后端获取一个唯一的token(如 UUID),存储在表单或本地(如localStorage、隐藏字段)。
2.	点击提交时,将token随请求一起发送给后端。
3.	后端校验token:若未使用过,则处理请求并标记token为 “已使用”;若已使用,则拒绝重复请求。
4.	前端提交后,清除本地token(或请求成功后由后端返回新token,供后续操作使用)。

• 优点:即使前端限制被绕过(如恶意攻击),后端仍能拦截重复请求,安全性高。

• 注意:需配合后端逻辑实现,适合对数据一致性要求高的场景(如支付、订单提交)。

一句话总结:

前端防呆是为了提升体验,后端校验才是防止重复提交的根本保障,而测试只有懂了原理才不会在缺陷站在眼前时还是熟视无睹。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-09-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 软件测试那些事 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档