如何停止其他代码运行,直到setTimeout()完成运行?

时间:2018-10-15 20:23:48

标签: javascript settimeout event-listener

我正在制作一个简单的存储卡游戏。如果您连续单击两张相同的卡片,它们将保持打开状态。如果您连续单击两张不同的卡片,它们都会在1.5秒内关闭。为此,我使用setTimeout();。但是,如果在1.5秒内用户单击任何其他卡,则事件监听器功能将再次运行,而setTimeout尚未首次运行。这会使游戏崩溃。如何防止其他代码在setTimeout第一次完成运行之前运行?任何建议都将不胜感激!

const cards = document.querySelectorAll('.container__small');
let hasFlippedCard = false;
let firstCard, secondCard;
let lockBoard = false;

cards.forEach(function (card) {
  return card.addEventListener('click', flipCard);
});

function flipCard(){
  this.classList.add('flip');
  if(!hasFlippedCard){ 
    //first click
    hasFlippedCard = true;
    firstCard = this;
  }else {
    //second click
    hasFlippedCard = false;
    secondCard = this;
    setTimeout(function(){
      if(firstCard.dataset.framework !== secondCard.dataset.framework ){
        firstCard.classList.remove('flip');
        secondCard.classList.remove('flip');
      }
    }, 1500);
  }
}

5 个答案:

答案 0 :(得分:2)

您不能阻止setTimeout()等待时运行JavaScript代码。这是JavaScript运行到完成/事件循环执行模型的本质。

在您的情况下,您应该有一个附加标志,在此期间不做任何事情:

const cards = document.querySelectorAll('.container__small');
let hasFlippedCard = false;
let firstCard, secondCard;
let lockBoard = false;  // <<< use this flag

cards.forEach(function (card) {
  return card.addEventListener('click', flipCard);
});

function flipCard(){
  if(lockBoard) return;  // <<< check flag
  this.classList.add('flip');
  if(!hasFlippedCard){ 
    //first click
    hasFlippedCard = true;
    firstCard = this;
  }else {
    //second click
    hasFlippedCard = false;
    secondCard = this;
    lockBoard = true; // <<< set flag
    setTimeout(function(){
      if(firstCard.dataset.framework !== secondCard.dataset.framework ){
        firstCard.classList.remove('flip');
        secondCard.classList.remove('flip');
      }
      lockBoard = false;  // <<< unset flag
    }, 1500);
  }
}

答案 1 :(得分:1)

function flipCard(){
  if (lockBoard) {
    return
  }
....

结束您的setTimeout函数

lockBoard = true
setTimeout(function(){
  ....
  lockBoard = false
}, 1500)

答案 2 :(得分:0)

setTimeout返回一个正整数,该整数标识由setTimeout创建的计时器,因此如果您有类似以下内容:

var myTimer = setTimeout(function(){
  console.log( 'executed' );
}, 1500);

您可以使用clearTimeout( timeoutId ),其中timeoutIdmyTimer的值,因此类似clearTimeout( myTimer )的东西将在未执行时取消该计时器的执行。

类似:

var myTimer = setTimeout(function(){
  console.log( 'executed' );
}, 1500);

if ( myTimerId ) {
    clearTimeout( myTimerId );
}

可以将if块中的代码放在上面的click这样的事件侦听器中,以便您可以在再次单击该事件时取消计时器。 / p>

答案 3 :(得分:0)

使用布尔值标志确定超时是否正在进行,如果超时,则不执行回调。

const cards = document.querySelectorAll('.container__small');
let cardIsFlipping = false;
let hasFlippedCard = false;
let firstCard, secondCard;
let lockBoard = false;

cards.forEach(function (card) {
  return card.addEventListener('click', flipCard);
});

function flipCard(){
  if(cardIsFlipping) {
     return;
  }

  this.classList.add('flip');
  if(!hasFlippedCard){ 
    //first click
    hasFlippedCard = true;
    firstCard = this;
  }else {
    //second click
    hasFlippedCard = false;
    secondCard = this;
    cardIsFlipping = true;
    setTimeout(function(){ 
      if(firstCard.dataset.framework !== secondCard.dataset.framework ){
        firstCard.classList.remove('flip');
        secondCard.classList.remove('flip');
      }
      cardIsFlipping = false;
    }, 1500);
  }
}

答案 4 :(得分:0)

尝试如下操作:在setTimeout函数之前禁用卡,并在函数执行后重新启用卡。

tableHeaderView