[英]How to stop other code from running until setTimeout() finishes running?
我正在做一个简单的记忆卡游戏。 如果您连续单击两张相同的卡片,它们将保持打开状态。 如果您连续单击两张不同的卡片,它们都会在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);
}
}
在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);
}
}
function flipCard(){
if (lockBoard) {
return
}
....
在您的setTimeout函数中结束
lockBoard = true
setTimeout(function(){
....
lockBoard = false
}, 1500)
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
一样,以便在再次单击事件时取消计时器。
使用布尔值标志确定超时是否正在进行,如果超时,则不执行回调。
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);
}
}
尝试如下操作:在setTimeout函数之前禁用卡,并在函数执行后重新启用它们。
document.querySelectorAll('.container__small').addAttribute("disabled",true);
setTimeout(function(){
if(firstCard.dataset.framework !== secondCard.dataset.framework ){
firstCard.classList.remove('flip');
secondCard.classList.remove('flip');
}
document.querySelectorAll('.container__small').removeAttribute("disabled");
}, 1500);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.