搜索

首页  >  问答  >  正文

javascript - ajax重复提交问题

再是用ajax提交表单的时候,经常出现重复提交,有通过token的,有提交后跳转页面的。想了解一下现在都有什么方法可以做这个?

PHP中文网PHP中文网2902 天前349

全部回复(6)我来回复

  • 高洛峰

    高洛峰2017-04-10 15:07:08

    ajax 防止重复提交处理:

    客户端:
    1. disabled 提交按钮
    2. 定义个变量 var hasSubmit = false,来处理。

    服务端:
    .....................

    回复
    0
  • 黄舟

    黄舟2017-04-10 15:07:08

    请搜索 CSRF

    回复
    0
  • 黄舟

    黄舟2017-04-10 15:07:08

    你点击按钮的时候,给这个按钮加上一个class,比如ub-click-able,如果有这个class,点击这个按钮不触发Ajax事件。当Ajax处理返回之后,你去掉这个class

    回复
    0
  • 迷茫

    迷茫2017-04-10 15:07:08

    提交后加 disabled 属性。

    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

    <code>var loginwrap = parent,

                btn = self,

                nameInput = loginwrap.find('input[name=name]'),

                pwdInput = loginwrap.find('input[name=pwd]'),

                nameError = nameInput.siblings('.errorMsg'),

                pwdError = pwdInput.siblings('.errorMsg'),

                name = nameInput.val(),

                pwd = pwdInput.val();

            $.ajax({

                type: 'POST',

                url: url,

                timeout: 3000,

                data: {

                    name: name,

                    pwd: pwd

                },

                beforeSend: function () {

     

                    nameError.text('');

                    pwdError.text('');

     

                    var checkname = yousi_tool.checkReg('phone', name),

                        checkpwd = yousi_tool.checkReg('password', pwd);

                    if (checkname !== true) { //手机号检测有误

                        nameError.text(checkname);

                        return false;

                    }

                    if (checkpwd !== true) { //密码检测有误

                        pwdError.text(checkpwd);

                        return false;

                    }

     

                    btn.text('登录中').attr('disabled', 'disabled');

                },

                success: function (data) {

                    if (data.code == 200) {

     

                    } else {

                        pwdError.text(data.desc);

                    }

     

                    btn.text('登录').removeAttr('disabled');

                },

                error: function () {

                    btn.text('登录').removeAttr('disabled');

                    pwdInput.siblings('.errorMsg').text('网络请求有误,请检查网络后再次登录');

                }

            })

    </code>

    回复
    0
  • 黄舟

    黄舟2017-04-10 15:07:08

    这是个大问题,服务器端最好还是要有检查策略,一般关键性的,容易重复提交的request会通过一些参数来保证是合法客户端合法用户的合理请求,像淘宝前端是采集你的各种操作、当前时间、随机码等等来拼成一个token,后端有对应算法来验证这个,保证你没法重复提交。

    回复
    0
  • 黄舟

    黄舟2017-04-10 15:07:08

    重复提交一般针对post请求,我的处理方法是这样:
    维护一个请求队列,每次post请求过来,生成一个包含url,data,timestamp的对象,push到队列中,后续每来一个post请求都对比一下,看请求队列中是否有url相同并且data相同的请求,如果有则认为是重复请求,当前请求丢弃掉。然后再遍历一下请求队列,比较每一个请求对象的timestamp和当前的timestamp,看请求是否超时,超时的话就将请求从队列中剔除。
    然后每个post请求得到响应后,将请求队列中对应的对象剔除掉。

    具体代码是这样的:

    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

    <code class="js">var interceptor = {

        reqQueue: [],

        timeout: 30000,

        beforeRequest: function(req) {

            if (req.method === "post") {

                // 创建请求对象

                var curReq = {

                    url: req.url,

                    data: JSON.stringify(req.data),

                    timestamp: Date.now()

                };

                 

                // 检测是否重复请求

                if (this.reqQueue.findIndex(item => item.url === curReq.url && item.data === curReq.data) === -1) {

                    // 非重复请求添加到请求队列

                    this.reqQueue.push(curReq);

                } else {

                    // 重复请求丢弃掉

                    req.abort();

                }

                 

                // 过滤掉超时请求

                this.reqQueue = this.reqQueue.filter(item => {

                    return Date.now() - item.timestamp < this.timeout

                });

            }

        },

         

        afterResponse: function(req, res) {

            if (req.method === "post") {

                // 过滤掉已完成请求

                this.reqQueue = this.reqQueue.filter(item => item.url === req.url && item.data === JSON.stringify(req.data));

            }

        }

    }</code>

    回复
    0
  • 取消回复