2017-08-05 80 views
1

我正在制作一个西蒙游戏,我试图让按钮有1秒的时间间隔。但似乎我的setTimeout函数没有完成它的工作,并且所有的点击都是在没有1s间隔的情况下一次执行的。我试着在循环之外提醒一些事情,它工作得很好。谁能帮我这个?JavaScript的setTimeout函数不能在循环内工作

这是我的JavaScript代码:

for (var count = 1; count <= 20; count++) { 
     $("#count").html(count); 
     seq.push(Math.floor(Math.random() * 4)); 
     seq.forEach(function(press) { 
     setTimeout(function() { 
      eval('$("#button' + press + '").click();'); 
     }, 1000); 
     }); 
    } 

和相应的HTML:

<p>count: <span id="count">0</span></p> 

    <button id="button0" onclick="sound1.play()"></button> 
    <button id="button1" onclick="sound2.play()"></button> 
    <button id="button2" onclick="sound3.play()"></button> 
    <button id="button3" onclick="sound4.play()"></button> 

谢谢!

+0

我还没有能弄明白。抱歉。 – Spacemoose

+0

所以你真的想要点击按钮210次,或者当你推进到你正在迭代的同一个数组时,你是否只有一个逻辑缺陷? – adeneo

+0

@adeneo是的,我真的想要按钮“点击”210次。确切地说,我想要20个系列的印刷机,每次再添加一个点击到以前的系列。这是西蒙比赛的一部分,我还没有涉足其他部分。 –

回答

1

问题是你的做法setTimeout

for循环在几毫秒内迭代,你基本上要求所有的点击运行一秒后,所以它们都在一秒后发生,但同时发生。

如果要求一个后第一次点击,两秒等之后第二次点击,你会得到你想要的东西:

seq.forEach(function(press, i) { 
    setTimeout(function() { 
     $("#button" + press).click(); 
    }, 1000 * i); 
    }); 

另外请注意,你可能要调整你的代码不做这个20倍:

for (var count = 1; count <= 20; count++) { 
    $("#count").html(count); 
    seq.push(Math.floor(Math.random() * 4)); 
} 

seq.forEach(function(press, i) { 
    setTimeout(function() { 
    $("#button" + press).click(); 
    }, 1000 * i); 
}); 
0

你的eval函数在1秒后运行,但它们都是。

会发生什么:当瓦亭为setTimeout的执行

loop from 1 to 20 
    add an item to the seq array 
    loop through the seq array 
     define the setTimeout to happen in 1 second. 

您的代码不睡觉。因此,所有这些都在循环中定义,并尽可能接近要求的1秒。

+0

谢谢!我真的认为代码应该在等待setTimeout时停止执行。 –

0

您可以通过从setTimeout内重复调用一个函数来创建一个异步循环:这样,排序和延迟就会按需要。

下面是一些其他的想法工作片段:

// First generate the array (only 8 to not annoy SO public): 
 
var seq = Array.from(Array(8), _ => Math.floor(Math.random() * 4)); 
 

 
function replay() { 
 
    // Iterate seq asynchronously 
 
    (function loop(i) { 
 
     if (i >= seq.length) return; // all done 
 
     $("#count").text(i+1); 
 
     $("#buttons>button").eq(seq[i]).click(); 
 
     setTimeout(loop.bind(null, i+1), 1000); 
 
    })(0); 
 
} 
 

 
$("#buttons>button").click(function() { 
 
    // Play sound here... 
 
    playNote([523, 659, 784, 880][$(this).index()], 800); 
 
    // Some visual effect: 
 
    $(this).addClass("clicked"); 
 
    setTimeout($(this).removeClass.bind($(this), "clicked"), 800); 
 
}); 
 

 
// Sound support 
 
var audioCtx = new (window.AudioContext || window.webkitAudioContext)(); 
 

 
function playNote(frequency, duration) { 
 
    // create Oscillator node 
 
    var oscillator = audioCtx.createOscillator(); 
 
    oscillator.type = 'square'; 
 
    oscillator.frequency.value = frequency; // value in hertz 
 
    oscillator.connect(audioCtx.destination); 
 
    oscillator.start(); 
 
    setTimeout(oscillator.stop.bind(oscillator), duration); 
 
} 
 

 
// Play the sequence on page load 
 
replay();
button { 
 
    border: 2px solid silver; 
 
} 
 
button.clicked { 
 
    border: 2px solid red; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<p>count (up to 8): <span id="count">0</span></p> 
 

 
<div id="buttons"> 
 
    <button>A</button> 
 
    <button>B</button> 
 
    <button>C</button> 
 
    <button>D</button> 
 
</div>

+0

谢谢!它并不完全符合我的希望,但它确实有帮助。我也很喜欢你产生阵列的方式 –

+0

不客气。你想以不同的方式工作? – trincot

+0

我想让它播放任意数量的音符。但是我已经通过给函数添加了一个参数来解决它。非常感谢! –