协慌网

登录 贡献 社区

setTimeout 或 setInterval?

据我所知,这两段 JavaScript 的行为方式相同:

选项 A:

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

myTimeoutFunction();

选项 B:

function myTimeoutFunction()
{
    doStuff();
}

myTimeoutFunction();
setInterval(myTimeoutFunction, 1000);

使用setTimeoutsetInterval之间有什么区别?

答案

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

Altough 人们可能认为setInterval将执行每正是 1000 毫秒,这是需要注意的重要setInterval也将推迟,因为 JavaScript 是不是多线程的语言,这意味着 - 如果有运行脚本的其他部分 - 区间将不得不等待完成。

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

延迟几乎总是可以忽略不计,但是如果您要编写非常精确的内容,则应该使用自调整计时器 (本质上是基于超时的计时器,它会根据所创建的延迟不断进行自我调整)

有什么区别吗?

是。在调用 setTimeout()之后,超时将执行一定的时间;间隔在上一个间隔触发后执行一定的时间。

如果 doStuff()函数需要一段时间才能执行,您会注意到其中的区别。例如,如果我们用表示对 setTimeout / setInterval 的调用. ,使用*触发超时 / 间隔,并使用[-----]触发 JavaScript 代码执行,时间轴如下所示:

Timeout:

.    *  .    *  .    *  .    *  .
     [--]    [--]    [--]    [--]

Interval:

.    *    *    *    *    *    *
     [--] [--] [--] [--] [--] [--]

下一个难题是,如果 JavaScript 已在忙于执行某项操作(例如处理上一个间隔)时触发了一个间隔。在这种情况下,该间隔将被记住,并在前一个处理程序完成并将控制权返回给浏览器后立即发生。例如,对于一个有时短([-])有时长([-----])的 doStuff()过程:

.    *    *    •    *    •    *    *
     [-]  [-----][-][-----][-][-]  [-]

• 表示无法立即执行其代码的间隔触发,而是改为挂起。

因此,间隔尝试 “赶上” 以恢复原定计划。但是,它们不会彼此排长队:每个间隔只能有一个执行挂起。 (如果他们都排队,那么浏览器将获得不断扩大的出色执行列表!)

.    *    •    •    x    •    •    x
     [------][------][------][------]

x 表示无法执行或待定的间隔触发,因此被丢弃。

如果您的 doStuff()函数习惯性地花费比为其设置的时间间隔执行的时间更长的时间,则浏览器将消耗 100%的 CPU 尝试为其服务,并且响应速度可能会降低。

您使用哪个?为什么?

链接超时为浏览器提供了一定的空闲时间。 Interval 尝试确保正在运行的功能尽可能接近其计划时间执行,但以牺牲浏览器 UI 可用性为代价。

我会考虑一次平滑的动画间隔,我希望尽可能平滑,而链式超时对于在页面加载过程中始终出现的正在进行的动画更礼貌。对于要求不高的用途(例如每 30 秒触发一次琐碎的更新程序),您可以放心使用。

在浏览器兼容性方面,setTimeout 早于 setInterval,但是您今天将要使用的所有浏览器都支持这两种。多年以来的最后一次失败是 WinMo <6.5 中的 IE Mobile,但希望现在也已经过去。

setInterval()

setInterval()是基于时间间隔的代码执行方法,具有在达到间隔时重复运行指定脚本的本机功能。脚本作者不应其嵌套在其回调函数中以使其循环,因为它默认情况下循环 。除非您调用clearInterval()否则它将一直间隔触发一次。

如果要循环播放动画或时钟滴答声的代码,请使用setInterval()

function doStuff() {
    alert("run your code here when time interval is reached");
}
var myTimer = setInterval(doStuff, 5000);

setTimeout()

setTimeout()是将要执行的脚本只有一个到达间隔时间时基于时间的代码执行方法。除非您通过将setTimeout()对象嵌套在它调用运行的函数内来调整它来循环脚本,否则它不会再次重复。如果适合循环,它将保持间隔触发,除非您调用clearTimeout()

function doStuff() {
    alert("run your code here when time interval is reached");
}
var myTimer = setTimeout(doStuff, 5000);

如果您希望在指定的时间段后发生某件事,请使用setTimeout() 。这是因为仅在达到指定间隔时才执行一次。