据我所知,这两个javascript的行为方式相同:

选项A:

function myTimeoutFunction()
{
    doStuff();
    setTimeout(myTimeoutFunction, 1000);
}

myTimeoutFunction();

选项B:

function myTimeoutFunction()
{
    doStuff();
}

myTimeoutFunction();
setInterval(myTimeoutFunction, 1000);

使用setTimeout和setInterval之间有什么区别吗?


当前回答

选项A和选项B看起来工作相同的原因主要是因为setInterval和setTimeout函数的位置不同。

function myTimeoutFunction()
{
    doStuff();
    setTimeout(myTimeoutFunction, 1000);
}

myTimeoutFunction();

这是一个递归函数,如果doStuff非常复杂,则setTimeout必须跟踪setTimout的所有调用以及当前的doStuff,这会使它变得更慢,而且速度更快。

function myTimeoutFunction()
{
    doStuff();
}

myTimeoutFunction();
setInterval(myTimeoutFunction, 1000);

另一方面,setInterval只需要跟踪上一个setInterval和当前的doStuff,使其保持恒定的速度。

So which one should you use?

从上面的内容中,您应该能够得出结论,更好的方法是setInterval。

其他回答

从另一个角度来看:setInterval确保代码在每个给定的时间间隔(即1000毫秒,或您指定的时间间隔)运行,而setTimeout设置它“等待”直到运行代码的时间。而且,由于运行代码需要额外的毫秒,所以它总共需要1000毫秒,因此setTimeout会以不精确的时间(超过1000毫秒)再次运行。

例如,计时器/倒计时不是用setTimeout完成的,而是用setInterval完成的,以确保它不会延迟,并且代码以精确的给定间隔运行。

要考虑的重要一点是性能。使用setTimeout周期性运行函数的唯一方法是用目标函数递归地调用它,当您检查它时,它似乎以异步方式工作。当您看到调用堆栈时,您会发现它一直在增长。事实上,这是明智的。由于Javascript不支持多线程,因此不可能在完成子函数之前完成对父函数的调用,因此,只要有递归调用,堆栈就会继续增长。同时,使用setInterval,我们不需要递归调用目标函数,因为它有一个作为循环周期性运行的逻辑。因此,这保持了调用堆栈的清洁。您可以在浏览器中使用开发人员的工具查看调用堆栈,您会注意到其中的差异。

当长时间使用小间隔时,差异将很明显。

只是添加到已经说过的内容上,但setTimeout版本的代码也将达到最大调用堆栈大小,这将使其停止运行。因为递归函数没有停止的基本情况,所以不能让它永远运行。

我对setInterval(func,milisec)进行了简单的测试,因为我很好奇当函数时间消耗大于间隔持续时间时会发生什么。

setInterval通常会在上一次迭代开始之后安排下一次迭代,除非函数仍在运行。如果是,setInterval将等待,直到函数结束。一旦发生,函数就会立即再次启动——不需要根据计划等待下一次迭代(因为在没有时间超过函数的情况下)。并行迭代也没有运行的情况。

我已经在Chrome v23上测试过了。我希望它在所有现代浏览器中都是确定性的实现。

window.setInterval(function(start) {
    console.log('fired: ' + (new Date().getTime() - start));
    wait();
  }, 1000, new Date().getTime());

控制台输出:

fired: 1000    + ~2500 ajax call -.
fired: 3522    <------------------'
fired: 6032
fired: 8540
fired: 11048

wait函数只是一个线程阻塞助手-同步ajax调用,在服务器端需要2500毫秒的处理时间:

function wait() {
    $.ajax({
        url: "...",
        async: false
    });
}

控制台的区别很明显: