首页新闻找找看学习计划

如果防止或避免Ajax 的重复提交?

0
悬赏园豆:20 [已解决问题] 解决于 2018-02-28 17:14

下面是我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) 来模拟点击按钮后,再刷新页面,然而本地是正常的,第二个数据已经无法提交了。

问题补充:

会不会是多个线程同时请求时,就会出现这个问题?

BUTTERAPPLE的主页 BUTTERAPPLE | 老鸟四级 | 园豆:2948
提问于:2017-12-26 17:38
< >
分享
最佳答案
0

submitFlag=true; 放在方法里面,导致不起作用。

BUTTERAPPLE | 老鸟四级 |园豆:2948 | 2018-02-28 17:13
其他回答(5)
0

推荐一篇园子里的一篇博文:一道面试题:如何防止异步请求的重复提交

收获园豆:5
dudu | 园豆:39077 (高人七级) | 2017-12-26 17:47
0

每一类请求,都分配一个唯一key,请求时,根据唯一key创建队列。

收获园豆:5
幻天芒 | 园豆:36522 (高人七级) | 2017-12-27 08:44

这应该就是 幂等性吧?

支持(0) 反对(0) BUTTERAPPLE | 园豆:2948 (老鸟四级) | 2017-12-27 11:47

@BUTTERAPPLE: 幂等指调用N次,输入一致,结果就一致。更多是针对后端api来说的。对于客户端来说,通过队列就能限制同一类api重复提交。 
a(); -> 加入队列,设定key=key1

a();->加入队列,设定key=key1

在执行队列时,会先判断当前key所在的队列是否为空,不为空则等待或其他操作。

支持(1) 反对(0) 幻天芒 | 园豆:36522 (高人七级) | 2017-12-27 22:20
0

光前端阻止重复提交还不够,还需要后端也要使用。

收获园豆:5
Supper_litt | 园豆:979 (小虾三级) | 2017-12-27 11:30

后端仅仅判断了如果数据库中有此条数据,则禁止提交。现在怀疑的是,可能是两个线程同时请求时,就会出现这样的情况。

支持(0) 反对(0) BUTTERAPPLE | 园豆:2948 (老鸟四级) | 2017-12-27 11:44

@BUTTERAPPLE: web天生就是多线程,怎么阻止。

支持(0) 反对(0) Supper_litt | 园豆:979 (小虾三级) | 2017-12-28 13:54

@Supper_litt: 还望指点一下。

支持(0) 反对(0) BUTTERAPPLE | 园豆:2948 (老鸟四级) | 2017-12-28 14:02

@BUTTERAPPLE: 

1、前端,你的js判断,状态在调用ajax之前,点击按钮之后,就做出判断(可以,禁用按钮,可以直接check状态,直接return; ),防止重复点击。

2、后端,输出页面,指定一个唯一值,作为提交的guid一起提交,校验。

3、最后才是数据层的防重复。

支持(1) 反对(0) Supper_litt | 园豆:979 (小虾三级) | 2017-12-28 14:23
0

可以考虑用promise 和es7中的async await

收获园豆:5
Or_so | 园豆:213 (菜鸟二级) | 2017-12-28 18:24
0

前端可以用定时器

var timer = null;

$(obj).click(function(){

    if(timer){

         clearTimeout(timer)

    }

   timer = setTimeout(fun(),20)

})

小小白~ | 园豆:194 (初学一级) | 2017-12-29 23:23
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册