防止ajax重复提交

同学们是不是经常遇到一个按钮多次提交ajax请求的情况发生?

造成这种情况的原因是ajax需要等待的时候太长,然后在等待的时候用户多次点击会出现多次ajax请求!最后多次ajax请求发生之后会被后端吐槽(也许是因为他们忘记在接口做限制 //蜜汁微笑)

该如何解决呢!

市面上的解决方案大抵是在ajax请求前加把锁锁住按钮,然后等后端接口返回信息后解锁,然后按钮又可以点击了,这样做到防止重复点击事件发生!!!
真的是炒鸡简单有效,现在我啥也不说,直接伤害炒鸡简单代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
<!DOCTYPE html>  
<html>
<head>
<meta charset="UTF-8">
<title>防止ajax重复提交</title>
</head>
<style>
*{padding: 0px;margin: 0px;}
#mask {
width: 100vw;
height: 100vh;
background: #000;
opacity: 0.2;
position: fixed;
left: 0;
top: 0;
display: none;
z-index: 999;
}
</style>
<body>
<div id="btn">我是一个按钮</div>
<div id="mask"></div>
<body>

<script>
var ajax = function(opt){
opt = opt || {};
opt.method = opt.method.toUpperCase() || 'POST';
opt.url = opt.url || '';
opt.async = opt.async || true;
opt.data = opt.data || null;
opt.success = opt.success || function () {};
var xmlHttp = XMLHttpRequest? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')

var params = [];
for (var key in opt.data){
params.push(key + '=' + opt.data[key]);
}
var postData = params.join('&');
if (opt.method.toUpperCase() === 'POST') {
xmlHttp.open(opt.method, opt.url, opt.async);
xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
xmlHttp.send(postData);
}else if (opt.method.toUpperCase() === 'GET') {
xmlHttp.open(opt.method, opt.url + '?' + postData, opt.async);
xmlHttp.send(null);
}
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
opt.success(xmlHttp.responseText);
}
}
}

var lock = false;
btn.onclick = function(){
if(lock) return;
lock = true
ajax({
method: "get",
url: "/api/data",
data: {
page: 1,
count: 5
},
success: function(res){
console.log(res)
lock = false;
}
})
}
</script>
</html>

说实话,世面上像我这种热心肠的人应该已经绝种了!!!我知道大部分同学可能都会直接复制粘贴代码了,然后一运行,***傻逼博主,贴的代码都运行不了!!!

其实不能怪我咯,宝宝好委屈咯,是因为浏览器自身是有跨域限制的,最后就是要启动一个web服务在访问服务上的html才能有效得避免以下跨域!!

首先你得先有node环境,如果你没有,请点击右上角XX,(因为你不可能是前端,你不会需要防止表单重复提交的解决方案!!!/托腮)

桌面新建文件夹,文件夹里新建一个index.html和一个index.js,index.html内容如上代码,index.js如下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
var http = require('http');
//引入文件读写模块fs
var fs = require('fs');


var sleep = function(ms){
var startTime = new Date().getTime();
var endTime = 3000 + startTime;
while(new Date().getTime() < endTime){}
}

var httpObj = http.createServer(function(req,res){


if(req.url.match('/api/data') != null){
console.time()
sleep(3000)
console.timeEnd()
var data = {"status":0,"data":{"films":"123"},"msg":"ok"}
res.end(JSON.stringify(data));
}else {
var url = req.url=='/'?'index.html':req.url;
fs.readFile('./'+url,'utf-8',function(err,data){
if(err){
res.write('404,您访问的页面不存在');
res.end();
}else{
res.write(data);
res.end();
}
});
}
});
//监听端口
httpObj.listen(80);

然后在新建文件夹下启动命令行工具,你应该有git吧!!!然后在命令行上输入node index, 然后在浏览器上访问localhost就可以看到页面了,然后点击按钮就可以看到效果啦!!

是不是很简单,很小白,就可以处理重复提交的问题了!!!

理想总是很丰满,现实总残酷得让人绝望。

我项目中ajax请求可不只一个哦,大概几十吧! 里面有很多ajax请求都需要防止重复提交,如果是项目开始的时候跟我提这个bug,我可能会一个个得去写,写几十把锁,so easy拉
但是我砖都搬完了,你叫我一个个去找再去写,老夫有点接受不了了!!

也幸亏我项目之前用了axios.js,我所有的请求都有一个过滤器,有一些公共的东西可以统一处理,例如所有请求都要的加载条和所有请求都要加时间戳来防止缓存,不然我一个个去加,可能我已经猝死了!

然后我一直在想这个过滤器上做文章,但是在上面加锁是不可能的,因为我们可能会同时请求几个借口拉取页面数据,几个你都同时加锁的话会导致一些接口无法使用,因为被锁住了! 我思考了好久,我个人觉得可以在html和css上做处理,我们可以定义一个html遮盖层,覆盖整个页面(透明度为0),然后ajax请求开始前就浮现出来,结束后隐藏,然后在过滤器上加上这个,就可以改一处代码,实现n处加锁了 /微笑

然后回到之前的index.html,click那块可以改成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
btn.onclick = function(){
mask.style.display = "block";
ajax({
method: "get",
url: "/api/data",
data: {
page: 1,
count: 5
},
success: function(res){
console.log(res)
mask.style.display = "none";
}
})
}

卧槽!!!牛逼呀,厉害呀!吊炸天呀!!!比以前少了2行代码呀!!

好了,这就是我处理重复提交的方法,我目前没有遇到什么大问题,可能是我的项目没有什么流量吧!如果有什么建议和我做得不足的地方可以微信或者QQ给我指出,作为回报,我可以在lol或者王者里面带你上分哦!亲! /蜜汁微笑