Javascript,setTimeout循环?

use*_*366 78 javascript timing settimeout setinterval

所以我正在制作一个音乐程序,需要多个javascript元素与另一个同步.我一直在使用setInterval,它最初工作得非常好但是随着时间的推移,元素逐渐变得不同步,而音乐程序则很糟糕.

我在网上看到setTimeout更准确,你可以用某种方式设置setTimeout循环但是我还没有找到一个通用版本来说明这是如何实现的.有人可以向我展示一个使用setTimeout无限循环的基本示例.

谢谢.或者,如果有办法通过setInterval或其他功能实现更多同步结果,请告诉我.

编辑:

基本上我有一些像这样的功能:

//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);
Run Code Online (Sandbox Code Playgroud)

它最初工作得非常好,但是在大约一分钟的过程中,声音明显不同步,因为我已经阅读了setInterval,我读过setTimeout可以更加一致地准确.

War*_*0ck 160

您可以setTimeout使用递归创建循环:

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

这个问题setInterval()setTimeout()是没有保证你的代码将在指定时间运行.通过setTimeout()递归使用和调用它,您可以确保在下一次代码迭代开始之前,超时内的所有先前操作都已完成.

  • 这种方法的问题在于,如果函数需要超过1000毫秒才能完成,那么这一切都会让人失望.这并不保证每1000ms执行一次.setInterval是. (4认同)
  • @TJC正确,但如果你的先前的操作在`setInterval()`重新执行之前没有完成,你的变量和/或数据可能会非常快地失去同步.例如,如果我正在为数据调整,并且服务器响应时间超过1秒,则使用`setInterval()`我的先前数据在下一次操作继续之前不会完成处理.使用这种方法,不能保证您的功能每秒都会启动.但是,保证您的先前数据将在下一个间隔开始之前完成处理. (4认同)

Joã*_*ulo 27

只是补充.如果你需要传递一个变量并迭代它,你可以这样做:

function start(counter){
  if(counter < 10){
    setTimeout(function(){
      counter++;
      console.log(counter);
      start(counter);
    }, 1000);
  }
}
start(0);
Run Code Online (Sandbox Code Playgroud)

输出:

1
2
3
...
9
10
Run Code Online (Sandbox Code Playgroud)

每秒一行.


Mat*_*and 11

假设两个时间都不准确,使用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);
}
Run Code Online (Sandbox Code Playgroud)

所以它第一次等待(至少)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);
}
Run Code Online (Sandbox Code Playgroud)


小智 7

处理音频定时的最佳方法是使用Web Audio Api,它有一个单独的时钟,无论主线程发生什么,都是准确的.克里斯威尔逊在这里有一个很好的解释,例子等:

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

浏览一下这个网站以获取更多的Web Audio API,它的开发完全符合您的要求.


Ped*_*ito 7

使用 setInterval()

setInterval(function(){
 alert("Hello"); 
}, 3000);
Run Code Online (Sandbox Code Playgroud)

上面的代码每 3 秒执行一次alert("Hello");


Dup*_*ngh 6

根据您的要求

只是给我看一个使用 setTimeout 循环的基本例子

我们有以下示例可以帮助您

var itr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var  interval = 1000; //one second
itr.forEach((itr, index) => {

  setTimeout(() => {
    console.log(itr)
  }, index * interval)
})
Run Code Online (Sandbox Code Playgroud)