Лучший способ предотвратить выполнение функции JavaScript, когда она уже есть или другой? - PullRequest
2 голосов
/ 01 сентября 2009

Я использую jquery, и я привязываю метод toggle к нескольким кнопкам на веб-странице. Это выглядит примерно так

$('.button').toggle(function(){
  // first function
}, function(){
  // second function
});

Однако в обеих этих функциях есть анимация. Таким образом, пользователь может нажать кнопку во время выполнения первой или второй функции. И это портит порядок элементов HTML и может заставить их переместиться в конец страницы. Потому что по сути то, что делают эти функции, это перемещать один элемент до конца при первом щелчке, а при другом щелчке перемещать его туда, где он был изначально.

Конечно, трудно нажимать кнопку, когда она перемещается по странице. Но это возможно.

Ответы [ 5 ]

5 голосов
/ 01 сентября 2009

Вы можете использовать флаг. Установите флаг isAnimating на true, когда анимация начинается, и false, когда она заканчивается. Любая последующая анимация может продолжаться, только если это значение равно false.

Вы также можете проверить, применяется ли : анимированный селектор к владельцу события. И основывайте свои решения на этом.

3 голосов
/ 01 сентября 2009

Вы можете использовать bool в качестве семифора. Очевидно, что это ни в коем случае не безопасно, но javascript не поддерживает блокировку, поэтому вы можете легко иметь тупики и / или условия гонки с этим подходом, но он будет работать 99,9% случаев:)

0 голосов
/ 01 сентября 2009

Вам нужна очередь. Вы можете создать его с помощью переменной семафора, но jQuery уже предоставляет ее, поэтому, возможно, вы захотите ее использовать:

$('.button').toggle(function() {
  $(document).queue("foo", function() {
    ...
  });
}, function() {
  $(document).queue("foo", function() {
    ...
  });
});

jQuery обычно использует очередь "fx" для сериализации анимации, но вы можете использовать эту очередь "foo" для чего угодно.

Очередь может быть помещена в любой объект, поэтому, возможно, вы захотите поместить ее в контейнер, в котором есть все .button объекты. Вы не можете поставить его на кнопку (это) сами, или вы вернетесь туда, где находитесь сейчас.

После того, как вы это сделаете, все, что вам действительно нужно, это прервать анимацию. Это можно сделать, явно очистив очередь "fx", или вы можете использовать $('.button').stop();, чтобы остановить все старые анимации.

0 голосов
/ 01 сентября 2009

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

$('.button').click( 
function () {
  if( $(self).is(":animated") {
    return false;
  }
  if($(self).is(".rolledup")) {
     self.apply(roll_window_down);    
  } else {
     self.apply(roll_window_up);    
  }
});



function roll_window_up() {
  $(self).addClass( 'rolledup' );

  // first function    
}

function roll_window_down() {
  $(self).removeClass( 'rolledup' );
  // first function    
}
0 голосов
/ 01 сентября 2009

Вам нужно поместить две функции, которые вы передаете для переключения, в контекст, в котором вы можете удерживать флаг для контроля входа в функцию: -

(function() {
  var toggling = false;
  $('.button').toggle(function(){
    if (!toggling) {
      toggling = true;           
      // first function
      toggling = false;
    } else {
      // whatever you want to happen if re-entrance attempted
    }
  }, function(){
    if (!toggling) {
      toggling = true;           
      // second function
      toggling = false;
    } else {
      // whatever you want to happen if re-entrance attempted
    }
  })
 )();

N.B. Сериализует все переключатели элементов, которые имеют класс .button. IOW есть только один флаг toggling для всех кнопок. Если вы хотите, чтобы каждая кнопка имела свой собственный флаг переключения: -

$('.button').each(function() {
  var toggling = false;
  $(this).toggle(function(){
    if (!toggling) {
      toggling = true;           
      // first function
      toggling = false;
    } else {
      // whatever you want to happen if re-entrance attempted
    }
  }, function(){
    if (!toggling) {
      toggling = true;           
      // second function
      toggling = false;
    } else {
      // whatever you want to happen if re-entrance attempted
    }
  });
 );
...