我正在制作一个简单的存储卡游戏。如果您连续单击两张相同的卡片,它们将保持打开状态。如果您连续单击两张不同的卡片,它们都会在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);
}
}
答案 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 )
,其中timeoutId
是myTimer
的值,因此类似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