在我的correctClick函数中,我将按钮单击与数组(buttonPressValidate)进行比较,该数组包含屏幕上突出显示的所有按钮ID。如果单击突出显示的按钮,则replayFlash函数会突出显示buttonPressValidate中的所有按钮,然后highLightSquare函数应该在replayFlash函数完成后亮起一个新的正方形。我遇到的问题是我的highLightSquare函数在突出显示新方块之前没有等待replayFlash函数完成。
var clickNum = 0;
function correctClick(buttons) {
$(".button").on("click", function() {
var thisClick = $(this).attr("id");
var matchBut = buttonPressValidate[clickNum];
if(thisClick == matchBut) {
clickNum++;
setTimeout(function() {
replayFlash(buttonPress);
if(buttonPressValidate.length === clickNum) {
setTimeout(function() {
highLightSquare(simonButtons);
}, 1500);
}
}, 1500);
}
});
}
function replayFlash(butPressArr) {
function eachColor(i) {
var litColor = $(butPressArr[i]);
setTimeout(function() {
litColor.addClass("lit");
if(litColor.attr("id") === "greenButton") {
greenButton.play();
} else if(litColor.attr("id") === "redButton") {
redButton.play();
} else if(litColor.attr("id") === "blueButton") {
blueButton.play();
} else if(litColor.attr("id") === "yellowButton") {
yellowButton.play();
}
setTimeout(function() {
litColor.removeClass("lit");
}, 1000 - (1000 / 3));
}, 1000 * (i + 1));
}
for(var i = 0; i < butPressArr.length; i++) {
eachColor(i);
}
}
答案 0 :(得分:0)
setTimeout的优点在于它是非阻塞的(即异步),所以你的应用程序可以做其他事情,直到计时器熄灭。
除非在时间到期之前不希望执行继续执行,否则有时会出现setTimeout问题。您的replayFlash函数在播放序列之前返回,因为setTimeout不会阻止。代码的执行将一直持续到setTimeout间隔结束为止。
您需要一个同步/阻止计时器。一个例子是already on SO (click here to view)。下面我重写了你的replayFlash函数(未经测试)以使用这个阻塞等待模式。希望这会指出你正确的方向。您还需要以类似的方式修改您的correctClick函数。
// from @thinkbonobo's answer here:
// https://stackoverflow.com/questions/6921895/synchronous-delay-in-code-execution
function wait(ms) {
var start = Date.now(),
now = start;
while (now - start < ms) {
now = Date.now();
}
}
function replayFlash(butPressArr) {
function eachColor(i) {
var litColor = $(butPressArr[i]);
wait(1000 * (i + 1));
litColor.addClass("lit");
if(litColor.attr("id") === "greenButton") {
greenButton.play();
} else if(litColor.attr("id") === "redButton") {
redButton.play();
} else if(litColor.attr("id") === "blueButton") {
blueButton.play();
} else if(litColor.attr("id") === "yellowButton") {
yellowButton.play();
}
wait(1000 - (1000/3));
litColor.removeClass("lit");
}
for(var i = 0; i < butPressArr.length; i++) {
eachColor(i);
}
}
修改强>
受到上述用户Roamer-8888评论的启发,我想提出另一个选择:承诺。这实际上是IMO的“正确”答案,但它是一个更先进的概念。通过“等待”,Promise可让您控制异步环境中代码的执行,直到“履行”或“已解决”未来操作的承诺。
现在许多浏览器本身都支持promises,但有些浏览器需要一个库,所以让我们看一下流行的“Q”promise库的例子。这是一个简单的例子,说明如何使用promise等到setTimeout超时,然后继续执行其他操作。请注意,Q库(来自q.min.js)创建了用于创建promise的全局变量Q.
<script src='//cdnjs.cloudflare.com/ajax/libs/q.js/0.9.2/q.min.js'></script>
<script>
function myPatientFunction(message) {
var deferred = Q.defer();
setTimeout(function() {
console.log(message);
deferred.resolve();
}, 1000)
return deferred.promise;
}
myPatientFunction("Hello world")
.then(function() {
console.log("See? I waited my turn")
})
</script>
或者,使用most browsers support:
的原生承诺<script>
function myPatientFunction(message) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log(message);
resolve();
}, 1000)
});
}
myPatientFunction("Hello world")
.then(function() {
console.log("See? I waited my turn")
})
</script>