我正在制作一个Simon Says计划,我遇到了调用计算机的一系列动作并在屏幕上显示它们的问题。
我正在尝试使用此aiMoves()函数迭代数组并通过突出显示相应的颜色按钮来显示每个移动。我试图使用setInterval使第一个按钮高亮显示,程序等待一秒钟,然后下一个按钮高亮显示如下:
function aiTurns(randNum){
for(var i = 0; i < aiMoves.length; i++) {
if(aiMoves[i] === 1){
//sound1();
$('#green').addClass("active");
setTimeout(function(){
$('#green').removeClass("active");
}, 500);
}
else if(aiMoves[i] === 2){
//sound2();
$('#red').addClass("active");
setTimeout(function(){
$('#red').removeClass("active");
}, 500);
}
else if(aiMoves[i] === 3) {
//sound3();
$('#yellow').addClass("active");
setTimeout(function(){
$('#yellow').removeClass("active");
}, 500);
}
else if(aiMoves[i] === 4){
//sound4();
$('#blue').addClass("active");
setTimeout(function(){
$('#blue').removeClass("active");
}, 500);
}
level--;
playerTurn = true;
}
}
我这样称呼它:
var moves = function() {
aiTurns(randomNumber());
}
setInterval(moves, 2000);
}
问题是setInterval是异步的,并且同时调用aiMoves()中for循环的所有迭代。如何设置它以便数组的第一个元素执行,暂停,然后执行下一个元素?
这是用于更好的可视化的codepen: https://codepen.io/nick_kinlen/pen/oGjMMr?editors=0010
答案 0 :(得分:2)
由于for
循环会立即运行直到完成,因此您需要一种不同的方式来串行运行异步代码。这是一个简单的抽象,它允许您在每次迭代之间循环遍历一个给定延迟的数组:
function intervalForEach (array, iteratee, delay) {
let current = 0
let interval = setInterval(() => {
if (current === array.length) {
clearInterval(interval)
} else {
iteratee(array[current])
current++
}
}, delay)
}
所有条件逻辑都可以进入iteratee函数,该函数只接受数组中的当前项。 Here's一个有效的例子。
答案 1 :(得分:0)
这是使用异步/等待的另一种方式:
const timeout = ms => new Promise(res => setTimeout(res, ms));
(async () => {
var i = 1;
while (true) {
await timeout(1000);
// iteration logic
console.log(i++);
// termination logic
if(i > 10) {
break;
}
}
console.log("done");
})();
此处设置的间隔完全被Promise,setTimeout和await替换为while loop。