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

选项A:

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

myTimeoutFunction();

选项B:

function myTimeoutFunction()
{
    doStuff();
}

myTimeoutFunction();
setInterval(myTimeoutFunction, 1000);

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


当前回答

当您运行以下javascript或检查此JSFiddle时,您可以自己验证bobcen答案

<div id="timeout"></div>
<div id="interval"></div>

var timeout = 0;
var interval = 0;

function doTimeout(){
    $('#timeout').html(timeout);
    timeout++;
    setTimeout(doTimeout, 1);
}

function doInterval(){
    $('#interval').html(interval);
    interval++;
}

$(function(){
    doTimeout();
    doInterval();
    setInterval(doInterval, 1);
});

其他回答

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

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

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

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

我对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
    });
}

当您运行以下javascript或检查此JSFiddle时,您可以自己验证bobcen答案

<div id="timeout"></div>
<div id="interval"></div>

var timeout = 0;
var interval = 0;

function doTimeout(){
    $('#timeout').html(timeout);
    timeout++;
    setTimeout(doTimeout, 1);
}

function doInterval(){
    $('#interval').html(interval);
    interval++;
}

$(function(){
    doTimeout();
    doInterval();
    setInterval(doInterval, 1);
});

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

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

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

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

myTimeoutFunction();

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