Javascript,setTimeout循环?

所以我正在研究一个需要多个javascript元素与另一个同步的音乐程序。 我一直在使用setInterval,它起初工作得非常好,但是随着时间的推移,元素逐渐失去与音乐节目同步的不好的一面。

我已经在网上阅读setTimeout更准确,你可以有setTimeout循环不知何故,但我还没有find一个通用的版本,说明如何这是可能的。 有人能告诉我一个使用setTimeout无限循环的基本例子。

谢谢。 或者,如果有一种方法可以通过setInterval甚至另一个函数实现更多的同步结果,请让我知道。

编辑:

基本上我有这样的function:

//drums setInterval(function { //code for the drums playing goes here },8000); //chords setInterval(function { //code for the chords playing goes here },1000); //bass setInterval(function { //code for the bass playing goes here },500); 

它起初工作得非常好,但在一分钟的过程中,声音变得明显不同步,因为我读了setInterval发生,我读了setTimeout可以更一致的准确。

你可以使用recursion创build一个setTimeout循环:

 function timeout() { setTimeout(function () { // Do Something Here // Then recall the parent function to // create a recursive loop. timeout(); }, 1000); } 

setInterval()setTimeout()的问题是不能保证你的代码能在指定的时间内运行。 通过使用setTimeout()并recursion调用它,您可以确保在下一次代码迭代开始之前,超时内的所有先前操作都已完成。

既然时间不会很准确,那么使用setTimeout更准确一点的方法是计算自上一次迭代以来延迟的时间,然后适当地调整下一次迭代。 例如:

 var myDelay = 1000; var thisDelay = 1000; var start = Date.now(); function startTimer() { setTimeout(function() { // your code here... // calculate the actual number of ms since last time var actual = Date.now() - start; // subtract any extra ms from the delay for the next cycle thisDelay = myDelay - (actual - myDelay); start = Date.now(); // start the timer again startTimer(); }, thisDelay); } 

所以第一次它会等待(至less)1000毫秒,当你的代码被执行的时候,可能会有点晚,比如1046毫秒,所以我们从下一个周期的延迟中减去46毫秒,下一个延迟将会是只有954毫秒。 这不会阻止计时器开始迟到(这是预料之中),但可以帮助你阻止延迟。 (注意:你可能想检查这个延迟thisDelay < 0 ,这意味着延迟是你的目标延迟的两倍多,你错过了一个周期 – 你要如何处理这种情况)。

当然,这可能不会帮助你保持几个定时器同步,在这种情况下,你可能想弄清楚如何用同一个定时器来控制它们。

所以看你的代码,所有的延迟是500的倍数,所以你可以做这样的事情:

 var myDelay = 500; var thisDelay = 500; var start = Date.now(); var beatCount = 0; function startTimer() { setTimeout(function() { beatCount++; // your code here... //code for the bass playing goes here if (count%2 === 0) { //code for the chords playing goes here (every 1000 ms) } if (count%16) { //code for the drums playing goes here (every 8000 ms) } // calculate the actual number of ms since last time var actual = Date.now() - start; // subtract any extra ms from the delay for the next cycle thisDelay = myDelay - (actual - myDelay); start = Date.now(); // start the timer again startTimer(); }, thisDelay); } 

只有补充。 如果你需要传递一个variables并迭代它,你可以这样做:

 function start(counter){ if(counter < 10){ setTimeout(function(){ counter++; console.log(counter); start(counter); }, 1000); } } start(0); 

输出:

 1 2 3 ... 9 10 

每秒一行

处理audio时序的最好方法是使用Web Audio Api,它具有独立的时钟,无论主线程中发生了什么,都是精确的。 Chris Wilson在这里有一个很好的解释,例子:

http://www.html5rocks.com/en/tutorials/audio/scheduling/

看看这个网站的更多的WebaudioAPI,它被开发来做你到底是什么。

我认为最好在函数结束时暂停。

 function main(){ var something; make=function(walkNr){ if(walkNr===0){ // var something for this step // do something } else if(walkNr===1){ // var something for that step // do something different } // *** // finally else if(walkNr===10){ return something; } // show progress if you like setTimeout(funkion(){make(walkNr)},15,walkNr++); } return make(0); } 

这三个函数是必需的,因为第二个函数中的variables每次都会被默认值覆盖。 当程序指针到达setTimeout时,已经计算了一步。 那么只需要一点时间的屏幕。

以下代码工作正常

 var time = 0; for (var i = 0; i < 5; i++) { time += 1000; setTimeout(function() { console.log("var is now", i); }, time); }