前端防止用户重复提交:jQuery异步与表单同步方案详解

作者:白帽猫时间:2026-10-22 17:37:15浏览:337

本文详细介绍前端防止用户重复提交的两种方案。针对异步请求,利用jQuery的ajaxPrefilter拦截器过滤后续请求;针对表单同步提交,通过扩展jQuery自定义方法设置标志位阻止重复触发。文章提供完整代码示例及全站统一处理的实现技巧,帮助开发者高效解决重复提交问题。

前端防止重复提交背景与方案概述

背景

在前端向后端提交数据时,通常需要确保在第一次请求返回前,阻止用户因快速点击而发送二次请求,即防止重复提交。最直观的方法是设置标志参数或操作class元素,但这种方式要求在每个需要控制的地点手动添加逻辑,重复性高且控制逻辑难以统一。

由于前端目前主要使用HTTP协议,数据提交方式主要分为两种:

  • 异步提交,通常使用jQuery.ajax()方法实现。
  • 表单同步提交,即传统的Form表单提交方式。

下文将分别详细介绍这两种方法的具体实现示例,请跟随介绍逐步了解。

异步请求防重复提交实现

以下是异步请求防重复提交的解决方案。

利用jQuery提供的ajaxPrefilter方法,可以在请求提交前进行过滤,仅保留第一次请求,后续请求则通过abort方法阻止。具体实现代码如下:


/**
 * _pendingRequests = {
 * 'http:xxx.xxxx.do':['domain=P2P','xxxx=aaa'],
 * 'http:xxx.yyyy.do':['domain=P3P','xxxx=bbb']
 * }
 * 该对象的 key 是请求的 url ,value 是由请求参数转化成的字符串数组
 */
var _pendingRequests = {};
$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
 var p_item = { //保存请求请求的url
 key:options.url,
 index:0
 },
 dataArray = options.data ? options.data.split('&') : [];
 compareData = function(beforD,afterD) {
 //当url相同时,以此比较保存的参数对象,若参数对象相同,则返回false,若第一个就相同,则跳出循环
 // 反之说明当前参数对象列表中没有与将要提交的参数相同,则可看为不同的请求,返回true,允许发起请求
 var result = false;
 for(var i=0;i<beforD.length;i++){
 if(beforD[i]){
  result = false;
  var beforData = beforD[i];
  for(var j=0;j<beforData.length;j++){
  if(afterD[j] !== beforData[j]){
  result = true;
  break;
  }
  }
  if (!result){
  break;
  }
 }else {
  result = true;
  continue;
 }
 }
 return result;
 };

 //若请求队列中不存在或者同一个请求不同参数,且不为html后缀,则加入队列中
 if (( !_pendingRequests[p_item.key] || compareData(_pendingRequests[p_item.key],dataArray) ) && p_item.key.indexOf('.html') === -1) {
 //给 index 赋值是因为请求是异步返回的,index用于标记第一个请求
 if(_pendingRequests[p_item.key]){
 p_item.index = _pendingRequests[p_item.key].push(dataArray)-1;
 } else{
 _pendingRequests[p_item.key] = [dataArray];
 p_item.index = 0;
 }
 } else if (p_item.key.indexOf('.html') === -1) {
 jqXHR.abort(); // 放弃后触发的重复提交,仅保留第一次提交
 //pendingRequests[key].abort(); // 放弃先触发的提交
 }
 var complete = options.complete;
 //请求完成
 options.complete = function(jqXHR, textStatus) {
 // 通过 key 和 index 获取成功返回的请求,将其值为 null ,下一次该请求便是在请求队列中便是新的一个请求
 _pendingRequests[p_item.key][p_item.index] = null;
 if ($.isFunction(complete)) {
 complete.apply(this, arguments);
 }
 };
});

参考jquery.ajaxPrefilter官方文档

表单同步提交防重复提交方案

表单提交防重复提交的解决方案如下。

表单处理相对复杂,但核心思路与异步提交一致:在等待第一次请求返回的同时,阻止后续触发的请求发送。首先,基于jQuery扩展了一个自定义方法,实现如下:


$.fn.preventDoubleSubmission = function() {
 $(this).on('submit', function(e) {
 var $form = $(this);
 // $form.data('submitted') 通过该变量判断请求的状态
 if ($form.data('submitted') === true) {
 //阻止请求
 e.preventDefault();
 } else {
 $form.data('submitted', true);
 if ($form.attr('target') === '_blank') {
 setTimeout(function() {
  $form.data('submitted', false);
 }, 800);
 }
 }
 });
 return this;
};

当表单初次提交时,通过 jQuery.data() 设置一个标志位。当表单重复提交时,程序会判断该标志位;若处于提交状态,则阻止表单的提交事件。当 form.target = _blank 提交后打开新界面的情况,将在800毫秒后恢复原界面表单的可提交状态。

为了便于对全站表单提交进行统一处理,可以为需要防止重复提交的表单添加一个class preventDouble。在页面渲染完成后,统一添加事件监听即可。


//扫描带有 preventDouble 标识的form表单
$(function() {
 var f = $('.contain form.preventDouble');
 for (var i=0;i<f.length;i++){
 $(f[i]).preventDoubleSubmission();
 }
});

小贴士

  • 提交按钮需使用 type='submit' ,因为监听的是表单的submit事件。
  • 不建议多次监听submit事件,否则会导致防重复提交功能失效。
  • 在表单提交前通常会有表单校验操作,因此当校验失败时,可以通过 event.preventDefault() 阻止表单提交。

总结

以上就是本文的全部内容,希望这些内容对大家的学习或工作具有参考价值。如有疑问欢迎留言交流,感谢支持。

作者最新文章
相关文章
更多