【问题标题】:Ajax, prevent multiple request on clickAjax,防止点击多次请求
【发布时间】:2013-09-12 22:41:53
【问题描述】:

当用户单击登录或注册按钮时,我试图阻止多个请求。这是我的代码,但它不起作用。只是第一次工作正常,然后返回 false..

$('#do-login').click(function(e) {
    e.preventDefault();

    if ( $(this).data('requestRunning') ) {
        return;
    }

    $(this).data('requestRunning', true);

    $.ajax({
        type: "POST",
        url: "/php/auth/login.php",
        data: $("#login-form").serialize(),
        success: function(msg) {
            //stuffs
        },
        complete: function() {
            $(this).data('requestRunning', false);
        }
    });      
}); 

有什么想法吗?谢谢!

【问题讨论】:

    标签: javascript jquery ajax


    【解决方案1】:

    问题出在这里:

        complete: function() {
            $(this).data('requestRunning', false);
        }
    

    this 不再指向按钮。

    $('#do-login').click(function(e) {
        var me = $(this);
        e.preventDefault();
    
        if ( me.data('requestRunning') ) {
            return;
        }
    
        me.data('requestRunning', true);
    
        $.ajax({
            type: "POST",
            url: "/php/auth/login.php",
            data: $("#login-form").serialize(),
            success: function(msg) {
                //stuffs
            },
            complete: function() {
                me.data('requestRunning', false);
            }
        });      
    }); 
    

    【讨论】:

      【解决方案2】:

      使用on()off(),这就是它们的用途:

      $('#do-login').on('click', login);
      
      function login(e) {
          e.preventDefault();
          var that = $(this);
          that.off('click'); // remove handler
          $.ajax({
              type: "POST",
              url: "/php/auth/login.php",
              data: $("#login-form").serialize()
          }).done(function(msg) {
              // do stuff
          }).always(function() {
              that.on('click', login); // add handler back after ajax
          });
      }); 
      

      【讨论】:

      • 谢谢!乔的解决方案效果很好。但这是获得相同结果的另一种方式。哪个是最好的解决方案?
      • @adeneo 的解决方案更好。
      • @JoeFrambach - 谢谢,但这实际上是一个偏好问题,在 data() 中设置标志没有任何问题,但这似乎正是 on() 和 off() 的本意做,添加和删除事件处理程序?
      • 如果:用户单击按钮(因此发送 AJAX 请求)然后再次单击它(AJAX 仍未完成):不会调用 e.preventDefault(),因此按钮将提交形式(虽然它应该什么都不做)
      • @tigrou - 是的,如果它是一个表单,这可能会发生,但它很容易解决,只需将 preventDefault 添加到提交事件处理程序。
      【解决方案3】:

      您可以禁用该按钮。

      $(this).prop('disabled', true);
      

      【讨论】:

        【解决方案4】:

        在您的 ajax 回调中,上下文 (this) 从外部函数更改,您可以使用 $.ajax 中的 context 属性将其设置为相同

        $.ajax({
            type: "POST",
            url: "/php/auth/login.php",
            data: $("#login-form").serialize(),
            context: this, //<-----
            success: function(msg) {
                //stuffs
            },
            complete: function() {
                $(this).data('requestRunning', false);
            }
        });      
        

        【讨论】:

        • 感谢context选项的解释
        【解决方案5】:

        我也遇到过类似的问题。

        只需添加 $('#do-login').attr("disabled", true); 即可解决问题。

        $('#do-login').click(function(e) {
           e.preventDefault();
           $('#do-login').attr("disabled", true);
           .........
           .........
        

        这里do-login 是按钮ID。

        【讨论】:

          【解决方案6】:

          我已经尝试过这个并且对我来说工作得很好,我在 $.ajax 发送更多请求直到结果返回时遇到了麻烦,

           var settings = {
              "url": "/php/auth/login.php",
              "method": "POST",
              "timeout": 0,
              "async": false,
              "headers": {
                  "Content-Type": "application/json; charset=utf-8"
              },
              "data": jsondata, //data pass here is in JSON format
          };
          $.ajax(settings).done(function (ress) {
            try{
                console.log(ress, "Result from Ajax here");
              }
              catch(error){
                alert(error);
                console.log(ress);
              }
          });
          

          async : false 为我工作。 谢谢。

          【讨论】:

            【解决方案7】:

            或者你可以通过 $(this).addClass("disabled");给你的按钮或链接来实现,点击后你可以 $(this).removeClass("disabled");

            // CSS

            .disabled{
            cursor: not-allowed;
            
            }
            

            // JQUERY

            $('#do-login').click(function(e) {
               e.preventDefault();
            
                $(this).addClass("disabled");
                $.ajax({
                    type: "POST",
                    url: "/php/auth/login.php",
                    data: $("#login-form").serialize(),
                    context: this,
                    success: function(msg) {
                //do more here
            
                       $(this).removeClass("disabled");
                    },
                });
            });
            

            附:如果您使用引导 css,则不需要 css 部分。

            【讨论】:

              【解决方案8】:

              我发现这种方法很有用。我已经将它实现为带有 ES6 的 jQuery 的通用函数。

              export default function (button, promise) {
                  const $button = $(button);
                  const semaphore = 'requestRunning';
              
                  if ($button.data(semaphore)) return null;
                  $button.data(semaphore, true);
              
                  return promise().always(() => {
                      $button.data(semaphore, false);
                  });
              }
              

              因为$.ajax() 返回一个promise,所以你只需传入promise,剩下的就交给函数了。

              粗略地说,用法如下。

              import preventDoubleClick from './preventdoubleclick';
              
              ...
              
              button.click(() => {
                  preventDoubleClick(this, () => $.ajax()
                      .done(() => { console.log("success") }));
              });
              

              【讨论】:

                【解决方案9】:

                此功能可以帮助您控制多个 Ajax 请求,并且它具有超时功能,可以在 ex 之后将标志状态返回 0。 10 秒(如果服务器响应时间超过 10 秒)

                var Request_Controller = function(Request_Name = '', Reactivate_Timeout = 10000)
                {
                    var a = this;
                    a.Start_Request = function(){
                        if(window.Requests == undefined){
                            window.Requests = {};
                        }
                        window.Requests[Request_Name] = {'Status' : 1, 'Time': + new Date()};
                    }
                
                    a.End_Request = function(){
                        if(window.Requests == undefined){
                            window.Requests = [];
                        }
                        window.Requests[Request_Name] = undefined;
                    }
                
                    a.Is_Request_Running = function(){
                        if(window.Requests == undefined || window.Requests[Request_Name] == undefined){
                            return 0;
                        }else{
                            var Time = + new Date();
                            // Reactivate the request flag if server take more than 10 sec to respond
                            if(window.Requests[Request_Name]['Time'] < (Time - Reactivate_Timeout)) 
                            {
                                return 0;
                            }else{
                                return 1
                            }
                        }
                    }
                }
                

                使用它:

                var Request_Flag = new Request_Controller('Your_Request_Name');
                if(!Request_Flag.Is_Request_Running()){
                
                    Request_Flag.Start_Request();
                
                    $.ajax({
                        type: "POST",
                        url: "/php/auth/login.php",
                        data: $("#login-form").serialize(),
                        success: function(msg) {
                            //stuffs
                        },
                        complete: function() {
                            Request_Flag.End_Request();
                        }
                    }); 
                }
                

                【讨论】:

                  【解决方案10】:

                  用于防止整个站点中的多个 ajax 请求。例如:如果在其他 ajax 页面中使用 ajax 请求,在 php 循环中使用 ajax 等,给你多个 ajax 请求一个结果。我有解决办法:

                  Use window.onload = function() { ...  } 
                  

                  而不是

                  $(document).ready(function(){ ...  });
                  

                  在 index.php 主页面上。它将阻止所有多请求。 :)

                  【讨论】:

                    猜你喜欢
                    • 2014-11-29
                    • 1970-01-01
                    • 1970-01-01
                    • 2013-05-18
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多