Как избежать двойного вызова обработчика события en при быстрых кликах?

Существует кнопка, и когда пользователь нажимает кнопку, некоторые данные сохраняются в фоновом режиме. Проблема заключается в том, что пользователь быстро нажимает на кнопку, обработчик события выполняется несколько раз.

Это код

var x = 1;
$('#button').click(function() {
  // Do something
  // Save some data on network
  x++;
  console.log(x);
});

Я хочу, чтобы этот обработчик выполнялся, когда пользователь нажимает кнопку только один раз. Даже в случае двойного или триплексного щелчка это должно выполняться только один раз. Я просто хочу, чтобы избежать быстрых кликов, этот обработчик может снова выполнить кадр

У меня в голове много решений, например

  • Определите глобальную переменную типа IS_BUTTON_HANDLER_WORKING = false, и когда вы введете обработчик, установите его в true и в конце установите для него значение false. И проверьте, верно ли это только возврат из функции.

  • Отсоедините обработчик в начале и повторите попытку в конце.

У вас есть 25 кнопок в вашем приложении. Какой должен быть наилучший подход для реализации этого.

Посмотрите на Fiddle

Решение

$('#button').click(function() {
   $(this).attr('disabled', true);
  // Do something
  // Save some data on network
  $(this).removeAttr('disabled');
});

Используя это, мы уверены, что наш следующий обработчик будет выполнен только тогда, когда предыдущее выполнение было выполнено полностью.

Ответ 1

Дэвид Уолш имеет отличное решение .

// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
function debounce(func, wait, immediate) {
    var timeout;
    return function() {
        var context = this, args = arguments;
        var later = function() {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };
        var callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    };
};

Ответ 2

Существует несколько способов борьбы с этим:

Вы можете disable/hide после нажатия кнопки:

$('#button').attr("disabled", true);

Вы также можете установить таймаут для каждого щелчка, чтобы убедиться, что он не выполняется еще раз:

var x, y = 1;

$('#button').click(function() {
  if (x) clearTimeout(x);
  x = setTimeout(function() {
     // do the work here
     y++;
     console.log(y);
     // ----------------
  }, 1000);
});

Таким образом, каждый раз, когда нажимается кнопка, он фактически выполняет код только после 1000 milliseconds, если кнопка будет нажата в быстрой последовательности, тайм-аут будет просто очищен и начнется снова.

обратите внимание, что указанное выше не проверено

Лично я считаю, что отключенное решение является лучшим, поскольку оно указывает пользователю, что он нажал и что-то происходит, вы можете даже показать загрузчика рядом с кнопкой.

Ответ 3

Как отредактировать

Вы должны использовать . one()

или

Вы можете unbind событие при нажатии

var x = 1;
function myButtonClick() {

    $('#button').unbind('click');

    // Do something
    // Save some data on network
    x++;
    console.log(x);
    $('#button').bind('click', myButtonClick);
}

$('#button').bind('click', myButtonClick);

Ответ 4

Вы можете использовать метод jQuery one(), как показано здесь

Ответ 5

Я использую простое решение ниже, и оно хорошо работает для меня:

var x = 1;
e.handled=false;
$('#button').click(function(e) {
  if(e.handled==false){
      e.handled=true;
      // Do something
      // Save some data on network
      x++;
      console.log(x);      
  }
});

Ответ 6

Вы ищете this

$( "button" ).one( "click", function(evt) {
  x++;
  console.log(x);
});

Или, если вам нужен промежуток времени между двумя эффективными нажатиями.

var last, diff;
$( "button" ).click(function( event ) {
  if (last){
    diff = event.timeStamp - last;
    if (diff >= SOMEVAL){
      x++;
      console.log(x);    
    }
  }
  last = event.timeStamp;          
});

Ответ 7

var btn = document.querySelector('#twofuns');
btn.addEventListener('click',method1);
btn.addEventListener('click',method2);
function method2(){
  console.log("Method 2");
}
setTimeout(function(){
  btn.removeEventListener('click',method1);
},5000);
function method1(){
  console.log("Method 1");
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Pramod Kharade-RemoveEventListener after Interval</title>
</head>
<body>
<button id="twofuns">Click Me!</button>
</body>
</html>

Ответ 8

Попробуйте использовать следующий код

var x = 1;
var fewSeconds=10; /*10 seconds*/

$('#button').click(function() {
$('#button').attr("disabled", "disabled");
  x++;
  console.log(x);
    var btn = $(this);
    btn.prop('disabled', true);
    setTimeout(function(){
        btn.prop('disabled', false);
    }, fewSeconds*1000);

});

Ответ 9

Один из подходов состоит в том, чтобы просто удалить прослушиватель событий с кнопки и присоединить его впоследствии, если необходимо. В самой функции прослушивателя событий добавьте следующий код:

e.target.removeEventListener("click", handleBackButton);