首页 > 其他分享 >前端如何防止接口重复提交

前端如何防止接口重复提交

时间:2024-04-22 14:15:06浏览次数:22  
标签:function 请求 前端 接口 getElementById 提交 error document

什么是接口重复提交?

接口重复提交指的是在网络通信中,同一个请求被客户端多次发送到服务器端的情况。这种情况可能由于多种原因导致,例如用户在等待期间多次点击提交按钮、网络超时后客户端重新发送请求、客户端发送的请求在网络传输过程中出现重复等。

接口重复提交可能会导致多种问题,当服务器收到重复请求时,可能会多次处理相同的数据,导致数据重复操作或者产生不一致的结果。重复提交请求会增加服务器的负载和资源消耗,特别是在高并发情况下,可能会导致服务器压力过大,影响系统的性能和稳定性。有些请求是具有副作用的,例如支付、提交订单等,重复提交可能导致用户被重复扣款或者重复生成订单,从而导致业务异常或者用户不满。

下面我们就来看看前端有哪些防止接口重复提交的方法。

前端如何防止接口的重复提交?

禁用提交按钮

在用户点击提交按钮后,立即禁用该按钮,防止用户多次点击。可以在接口请求结束后重新启用按钮。代码如下所示。

<form id="myForm">
  <!-- 表单内容 -->
  <button type="submit" id="submitButton">提交</button>
</form>

<script>
document.getElementById('myForm').addEventListener('submit', function(event) {
  event.preventDefault(); // 阻止默认提交行为
  document.getElementById('submitButton').disabled = true; // 禁用提交按钮

  // 发送请求
  fetch('/api/submit', {
    method: 'POST',
    // 请求参数
  }).then(function(response) {
    // 处理响应
    document.getElementById('submitButton').disabled = false; // 启用提交按钮
  }).catch(function(error) {
    console.error('Error:', error);
    document.getElementById('submitButton').disabled = false; // 启用提交按钮(如果请求失败)
  });
});
</script>

显示加载状态

在用户提交表单后,显示一个加载状态的提示,告知用户正在处理请求,避免用户重复点击提交按钮。

<form id="myForm">
  <!-- 表单内容 -->
  <button type="submit" id="submitButton">提交</button>
  <div id="loadingMessage" style="display: none;">正在加载...</div>
</form>

<script>
document.getElementById('myForm').addEventListener('submit', function(event) {
  event.preventDefault(); // 阻止默认提交行为
  document.getElementById('submitButton').disabled = true; // 禁用提交按钮
  document.getElementById('loadingMessage').style.display = 'block'; // 显示加载状态

  // 发送请求
  fetch('/api/submit', {
    method: 'POST',
    // 请求参数
  }).then(function(response) {
    // 处理响应
    document.getElementById('submitButton').disabled = false; // 启用提交按钮
    document.getElementById('loadingMessage').style.display = 'none'; // 隐藏加载状态
  }).catch(function(error) {
    console.error('Error:', error);
    document.getElementById('submitButton').disabled = false; // 启用提交按钮(如果请求失败)
    document.getElementById('loadingMessage').style.display = 'none'; // 隐藏加载状态(如果请求失败)
  });
});
</script>

设置防抖或节流

在用户点击提交按钮后,使用防抖或节流的技术延迟发送请求,确保只发送一次请求。防抖和节流是一种常见的前端性能优化技术,可以控制函数的执行频率。

// 防抖函数
function debounce(func, delay) {
  let timer;
  return function() {
    clearTimeout(timer);
    timer = setTimeout(func, delay);
  };
}

document.getElementById('submitButton').addEventListener('click', debounce(function() {
  // 发送请求
  fetch('/api/submit', {
    method: 'POST',
    // 请求参数
  }).then(function(response) {
    // 处理响应
  }).catch(function(error) {
    console.error('Error:', error);
  });
}, 1000)); // 1秒内只允许点击一次

生成请求标识符

在每次请求前生成一个唯一的请求标识符(例如 UUID),并将该标识符作为请求的一部分发送到后端。后端在接收到请求后,检查该标识符是否已经处理过,如果已经处理过则不再处理。前端可以通过记录请求标识符的状态来避免重复提交。

// 生成唯一标识符
function generateRequestId() {
  return Math.random().toString(36).substr(2, 9);
}

let requestId;

document.getElementById('submitButton').addEventListener('click', function() {
  requestId = generateRequestId(); // 生成请求标识符
  // 发送请求
  fetch('/api/submit', {
    method: 'POST',
    headers: {
      'X-Request-Id': requestId // 将请求标识符添加到请求头中
    },
    // 请求参数
  }).then(function(response) {
    // 处理响应
  }).catch(function(error) {
    console.error('Error:', error);
  });
});

使用状态管理库

如果前端使用了状态管理库(如 Redux、Vuex 等),可以在提交请求前检查状态,确保不会重复提交相同的请求。

import store from './store'; // 引入状态管理库

document.getElementById('submitButton').addEventListener('click', function() {
  if (store.state.isSubmitting) {
    return; // 如果正在提交,则不执行后续操作
  }
  // 设置提交状态
  store.commit('setSubmitting', true);

  // 发送请求
  fetch('/api/submit', {
    method: 'POST',
    // 请求参数
  }).then(function(response) {
    // 处理响应
    store.commit('setSubmitting', false); // 恢复非提交状态
  }).catch(function(error) {
    console.error('Error:', error);
    store.commit('setSubmitting', false); // 恢复非提交状态(如果请求失败)
  });
});

接口锁定

在前端发送请求前,先检查是否存在正在处理的相同请求,如果存在则不发送新的请求。可以使用一个变量来记录当前正在处理的请求,以防止重复提交。

let isRequesting = false;

document.getElementById('submitButton').addEventListener('click', function() {
  if (isRequesting) {
    return; // 如果正在请求,则不执行后续操作
  }
  isRequesting = true; // 锁定接口

  // 发送请求
  fetch('/api/submit', {
    method: 'POST',
    // 请求参数
  }).then(function(response) {
    // 处理响应
    isRequesting = false; // 解锁接口
  }).catch(function(error) {
    console.error('Error:', error);
    isRequesting = false; // 解锁接口(如果请求失败)
  });
});

以上方法可以单独使用,也可以组合使用,以提高接口请求的可靠性和安全性。

总结

防止接口重复提交是为了确保系统的数据一致性、避免不必要的资源浪费和提升用户体验。为了避免接口重复提交带来的问题,需要在前端和后端都进行相应的处理,例如在前端禁用提交按钮、显示加载状态,在后端实现幂等性检查等。

标签:function,请求,前端,接口,getElementById,提交,error,document
From: https://www.cnblogs.com/houxianzhou/p/18150517

相关文章

  • 通用的后端返回给前端的状态信息Result
    packagecom.duxiang.backgroundmanagement.common;/***返回消息*/publicclassResult{privatestaticfinalStringSUCCESS="0";privatestaticfinalStringERROR="-1";privateStringcode;privateStringmsg;privateObj......
  • 前端页面渲染(文档+数据)不同模式
    一张可被用户访问的页面,可以被拆分为主文档(html)和数据两个部分,这两个部分既可以是组合在一起的(SSR),也可以是分离的(SPA、异步渲染)。比如一些活动搭建平台,可以增加一个数据网关,实现SSR,提升用户体验。服务端渲染(Server-SideRendering,SSR)服务端渲染是一种在服务器上生成完整......
  • springboot接口接收xml
    对xml文件的操作也可以借助hutool的XmlUtil.1.xml格式```xml<root> <deviceStatInfoonlineCount="64"offlineCount="2"errorCount="0"/> <data> <recordid="0"name="5号楼10层流量计"status="预警2/正常1......
  • 自动生成接口文档
    自动生成接口文档​ RESTframework可以自动帮我们生成接口文档。​ 接口文档以网页的形式呈现​ 自动接口文档能生成的是继承自APIView及其子类的视图使用步骤安装依赖​ RESTframework生成接口文档需要coreapi库的支持pipinstallcoreapi设置接口文档访问路径​ 需......
  • 前端资源共享方案对比-笔记:iframe/JS-SDK/微前端
    vue2异步加载之前说过,vue3还是之前的方法,只是把 i18n.setLocaleMessage改为i18n.global.setLocaleMessage但是本文还是详细说一遍:为什么需要异步加载语言包主要还是缩小提代码包,没有按需加载前,语言包内容太多好几屏幕全部是,虽然从webpack-analysis看图里面占比可以忽略不计......
  • 前端定义一个对象的时候,key值如何设置为数字,并抽成常量
    在JavaScript中,如果你想将对象的键值设置为常量数值,首先需要定义这些常量。然后你可以在创建对象时使用这些常量作为键。例如://定义常量constKEY_ONE=1;constKEY_TWO=2;constKEY_THREE=3;//使用常量作为对象的键letmyObject={[KEY_ONE]:'one',[KEY_T......
  • Reddit采集API reddit文章评论和搜索 实时数据接口
    近期调研发现iDataRiver平台https://www.idatariver.com/zh-cn/提供开箱即用的Reddit数据采集API,是目前用下来最方便简单的API,可以抓取reddit公开数据,例如subreddit中的帖子、按关键字搜索以及文章评论等,供用户按需调用。接口使用详情请参考RedditAPI接口接口列表1.获......
  • RPC接口和http接口的区别
    最本质的区别,就是RPC主要是基于TCP/IP协议的,而HTTP服务主要是基于HTTP协议的HTTP协议是在传输层协议TCP之上的,所以效率来看的话,RPC当然是要更胜一筹RPC服务RPC架构一个完整的RPC架构里面包含了四个核心的组件,分别是Client,Server,ClientStub以及ServerStub,这个S......
  • 前端【TS】03-typescript【基础】【Pinia】
    介绍 什么是PiniaPinia是Vue的专属的最新状态管理库,是Vuex状态管理工具的替代品 手动添加Pinia到Vue项目1.使用Vite创建一个空的TS+Vue3项目1npmcreatevite@latestvue-pinia-ts----templatevue-ts2.按照官方文档安装pinia到项......
  • 前端【TS】02-typescript【基础】【搭建Vite+Vue3+TS项目】【为ref标注类型】
    前置基于Vite创建Vue3+TS环境vite官方文档:https://cn.vitejs.dev/guide/vite除了支持基础阶段的纯TS环境之外,还支持Vue+TS开发环境的快速创建,命令如下:1npmcreatevite@latestvue-ts-project----templatevue-ts23//说明:41.npmcreatevite@lates......