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

选项A:

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

myTimeoutFunction();

选项B:

function myTimeoutFunction()
{
    doStuff();
}

myTimeoutFunction();
setInterval(myTimeoutFunction, 1000);

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


当前回答

如果您想取消超时,我发现setTimeout方法更容易使用:

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

myTimeoutFunction();

此外,如果函数中出现错误,它将在第一次错误时停止重复,而不是每秒重复错误。

其他回答

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

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

他们本质上试图做同样的事情,但setInterval方法将比setTimeout方法更准确,因为setTimeout等待1000ms,运行函数,然后设置另一个超时。因此,等待时间实际上比1000毫秒多一点(如果您的函数需要很长时间才能执行,则会更长)。

虽然有人可能认为setInterval将每1000ms执行一次,但需要注意的是,setInterval也会延迟,因为JavaScript不是一种多线程语言,这意味着,如果脚本的其他部分正在运行,则该间隔必须等待它完成。

在这个Fiddle中,您可以清楚地看到超时将落后,而时间间隔几乎一直都是1次/秒(脚本正在尝试这样做)。如果将顶部的速度变量更改为20这样的小值(意味着它将尝试每秒运行50次),则间隔将永远不会达到每秒50次迭代的平均值。

延迟几乎总是可以忽略不计的,但是如果你正在编程一些非常精确的东西,你应该使用一个自动调整的计时器(它本质上是一个基于超时的计时器,它会根据创建的延迟不断调整自己)

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

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

我使用setTimeout。

显然,区别在于setTimeout只调用一次方法,setInterval则重复调用它。

这是一篇很好的文章,解释了两者的区别:教程:带有setTimeout和setInterval的JavaScript计时器

如果将setInterval中的间隔设置得太短,则它可能会在上一次函数调用完成之前触发。我在最近的浏览器(Firefox 78)中遇到了这个问题。这导致垃圾收集无法足够快地释放内存,并造成了巨大的内存泄漏。使用setTimeout(函数,500);给垃圾收集足够的时间来清理和保持内存稳定。

Serg Hospodarets在他的回答中提到了这个问题,我完全同意他的说法,但他没有包括内存泄漏/垃圾收集问题。我也经历了一些冻结,但对于一些微不足道的任务,内存使用量很快就达到了4GB,这对我来说真的很糟糕。因此,我认为这个答案对我这种情况下的其他人仍然有益。我本想发表评论,但缺乏这样做的声誉。我希望你不介意。