防止代码在完成之前重新执行

时间:2013-05-05 18:50:10

标签: javascript jquery ajax asynchronous

我有以下情况:

$('button').on('click',function(){

    // Run AJAX commonds (May take some time);

});

因此,如果用户多次点击该按钮,他可能会执行很多ajax请求。

解决此问题的合理方法是使用

var finished = true;
$('button').on('click',function(){
    if(finished == true){
        finished = false;
        ....
        finished = true;
    }

但是为每个函数添加全局变量似乎很奇怪?我怎样才能解决这个问题?我查看了.off(),但这完全删除了该事件。 one()只执行一次。我不想多次执行。也许编写一个简单的插件来处理这个功能。它重复。

4 个答案:

答案 0 :(得分:0)

您可以添加数据或向该元素添加一个类,以指示它仍在处理中。如果操作完成,则删除该数据/类名。

$('button').on('click',function(){

  var self = $(this);
  var processing = self.data('processing');

  if(!processing){ //if not processing

    self.data('processing',true); //flag as processing

    //do stuff
    $.ajax({...}).done(function(responseData){

      //when done, unflag
      self.data('processing',false);
    });
  }
});

答案 1 :(得分:0)

一个选项可能是在请求处于活动状态时禁用该按钮。

$('button').click(function() {
    //or in the ajax beforeSend function
    $(this).prop('disabled', true);
    $.ajax({
        ...
        //or directly after the user clicked the button
        beforeSend: function() {
            $('button').prop('disabled', true);
        },
        ...
        //complete or success callback
        complete: function() {
            $('button').prop('disabled', false);
        }
    });
});

但是使用这种方法,你应该定义哪个按钮被禁用而不能再点击了。除非您希望禁用所有按钮。 我创建了一个 working example (jsfiddle) 供您测试。 (AJAX完成后延迟1秒,因此您会注意到禁用按钮)

使用Timeout可能是另一种选择,因此如果用户反复按下按钮,则不会触发AJAX调用。如果AJAX调用花费的时间超过了超时,则问题仍然存在。

var timer;    
$('button').on('click', function() {
    clearTimeout(timer);
    timer = setTimeout( function() {
        // Run AJAX commonds (May take some time);
    }, 500);

});

答案 2 :(得分:0)

了解.on() .off()方法的简单方法:http://jsbin.com/oguwux/1/edit

HTML:

<button id="btn">AJAX REQUEST</button>

jQuery的:

function ajaxCall(){

  $(this).off('click');
  $(this).text('Processing...'); // test only

  setTimeout(function(){  // (example.) do your AJAX call instead
    // ON SUCCESS :
    $('#btn').text('AJAX REQUEST');
    $('#btn').on('click', ajaxCall);
  },2000);

}

$('#btn').on('click', ajaxCall);

答案 3 :(得分:0)

这样的事情:(未经测试):

var InProgress = Array();
function OneAtATime($jQueryAjax) {
    var Id = arguments.callee.toString().match(/function\s+([^\s\(]+)/)
    InProgress.push(Id)

    for(var i=0; i<32; i++)
        result += Math.floor(Math.random()*16).toString(16).toUpperCase();
        return result
    }

    CallBacks = {
            success: function(x,y,z){$jQueryAjax.success(x,y,z);Remove(Id);,
            error: function(x,y,z){$jQueryAjax.error(x,y,z);Remove(Id);,
            fail: function(x,y,z){$jQueryAjax.fail(x,y,z);Remove(Id);
        }
}

function Remove(Id) {
    InProgress.splice(InProgress.indexOf(Id),1);
}

样本用法:

OneAtATime({
    /*  Usual jQuery.ajax properties  */
    url: '/Callback';
    success: function(data, status, xhhr) {
        alert('success');
    }

});

正如在另一个答案的评论中提到的那样,由于Javascript是单线程的,因此没有竞争条件。