下面是我Ajax的Post提交的代码:
function AddData() {
var a={},submitFlag=true;
a.qid=1;
$("#click_me").off("click").val("正在提交...").prop("disabled", true);
var startDate = new Date();
$.ajax({
timeout: 30000,//超时时间30s
type: "post",
data: a,
url: "/Home/AddData",
dataType: "Text",
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
beforeSend: function () {
if (!submitFlag) {
<span>alert</span>("正在提交,请稍后!");
return;
}
submitFlag = false;
},
success: function (data) {
if (data.indexOf("添加失败") !== -1) {
$("#click_me").val("添加").prop("disabled", false).on("click", function () {AddData() });
} else {
$("#append_data");
$("#click_me").val("添加").prop("disabled", false).on("click", function () {AddData() });
}
},
complete: function () {
submitFlag = true;
},
error: function (xhr, textStatus) {
if (textStatus === "timeout") {
console.log("Timeout");
} else {
}
$("#click_me").val("添加").prop("disabled", false).on("click", function () { AddData()});
}
});
};
我前端层面使用了点击后 Disable 按钮 以及 beforeSend 和 complete 来防止重复提交,后段里面我也判断了如果已有这个数据,则禁止提交。然后,有时候,在偶然情况下,我还是能够提交相同的两条数据。
请问这样要如何解决?以及在哪种情况下会出现这种情况?
我在本地使用 Task.Sleep(5000)
来模拟点击按钮后,再刷新页面,然而本地是正常的,第二个数据已经无法提交了。
会不会是多个线程同时请求时,就会出现这个问题?
submitFlag=true; 放在方法里面,导致不起作用。
每一类请求,都分配一个唯一key,请求时,根据唯一key创建队列。
这应该就是 幂等性吧?
@BUTTERAPPLE: 幂等指调用N次,输入一致,结果就一致。更多是针对后端api来说的。对于客户端来说,通过队列就能限制同一类api重复提交。
a(); -> 加入队列,设定key=key1
a();->加入队列,设定key=key1
在执行队列时,会先判断当前key所在的队列是否为空,不为空则等待或其他操作。
光前端阻止重复提交还不够,还需要后端也要使用。
后端仅仅判断了如果数据库中有此条数据,则禁止提交。现在怀疑的是,可能是两个线程同时请求时,就会出现这样的情况。
@BUTTERAPPLE: web天生就是多线程,怎么阻止。
@Supper_litt: 还望指点一下。
@BUTTERAPPLE:
1、前端,你的js判断,状态在调用ajax之前,点击按钮之后,就做出判断(可以,禁用按钮,可以直接check状态,直接return; ),防止重复点击。
2、后端,输出页面,指定一个唯一值,作为提交的guid一起提交,校验。
3、最后才是数据层的防重复。
可以考虑用promise 和es7中的async await
前端可以用定时器
var timer = null;
$(obj).click(function(){
if(timer){
clearTimeout(timer)
}
timer = setTimeout(fun(),20)
})