setTimeout或setInterval?

2020/09/21 04:01 · javascript ·  · 0评论

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

选项A:

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

myTimeoutFunction();

选项B:

function myTimeoutFunction()
{
    doStuff();
}

myTimeoutFunction();
setInterval(myTimeoutFunction, 1000);

使用setTimeoutsetInterval之间有什么区别

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

尽管有人可能会认为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()这是因为仅在达到指定间隔时才执行一次。

使用setInterval可以更轻松地取消将来执行代码。如果使用setTimeout,则必须跟踪计时器ID,以防日后要取消它。

var timerId = null;
function myTimeoutFunction()
{
    doStuff();
    timerId = setTimeout(myTimeoutFunction, 1000);
}

myTimeoutFunction();

// later on...
clearTimeout(timerId);

function myTimeoutFunction()
{
    doStuff();
}

myTimeoutFunction();
var timerId = setInterval(myTimeoutFunction, 1000);

// later on...
clearInterval(timerId);

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

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

myTimeoutFunction();

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

它们的目的非常不同。

setInterval()
   -> executes a function, over and over again, at specified time intervals  

setTimeout()
   -> executes a function, once, after waiting a specified number of milliseconds

就这么简单

更多详细信息,请参见http://javascript.info/tutorial/settimeout-setinterval

当您在setInterval中运行某些函数时,该函数的工作时间比timeout->更长,浏览器将被卡住。

-例如,doStuff()需要1500秒。要执行并执行:setInterval(doStuff,1000);

1)浏览器运行doStuff()耗时1.5秒。被执行;

2)〜1秒后,它将尝试再次运行doStuff()但是以前的doStuff()仍然会执行->因此浏览器将此运行添加到队列中(先完成后运行)。

3,4,..)将相同的内容添加到下一个迭代的执行队列中,但是上一个迭代的doStuff()仍在进行中...

结果,浏览器被卡住了。

为防止此行为,最好的方法是在setTimeout中运行setTimeout以模拟setInterval

要更正setTimeout调用之间的超时,可以使用JavaScript的setInterval技术的自更正替代方法。

您的代码将具有不同的执行间隔,在某些项目(例如在线游戏)中,这是不可接受的。首先,您应该怎么做才能使代码以相同的间隔工作,您应该将“ myTimeoutFunction”更改为:

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

更改之后,它等于

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

但是,由于JS是单线程的,因此结果仍然不稳定。目前,如果JS线程忙于处理某些事情,它将无法执行您的回调函数,并且执行将被延迟2-3毫秒。如果您每秒执行60次,并且每次都有1-3秒的随机延迟,那将是绝对不可接受的(一分钟后大约为7200毫秒的延迟),我建议您使用以下方式:

    function Timer(clb, timeout) {
        this.clb = clb;
        this.timeout = timeout;
        this.stopTimeout = null;
        this.precision = -1;
    }

    Timer.prototype.start = function() {
        var me = this;
        var now = new Date();
        if(me.precision === -1) {
            me.precision = now.getTime();
        }
        me.stopTimeout = setTimeout(function(){
            me.start()
        }, me.precision - now.getTime() + me.timeout);
        me.precision += me.timeout;
        me.clb();
    };

    Timer.prototype.stop = function() {
        clearTimeout(this.stopTimeout);
        this.precision = -1;
    };

    function myTimeoutFunction()
    {
        doStuff();
    }

    var timer = new Timer(myTimeoutFunction, 1000);
    timer.start();

此代码将保证稳定的执行期限。甚至线程都将繁忙,并且您的代码将在1005毫秒后执行,下一次它将有995毫秒的超时,结果将保持稳定。

我使用setTimeout。

显然,不同之处是setTimeout调用了该方法一次,setInterval重复调用了该方法。

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

我对进行了简单的测试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
    });
}

换个角度看:setInterval确保代码以每个给定的间隔(即1000ms,或您指定的时间)运行,而setTimeout设置它“等待”运行代码的时间。而且由于要花费额外的毫秒来运行代码,所以加起来总计为1000ms,因此setTimeout在不精确的时间(超过1000ms)再次运行。

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

setInterval和setTimeout都返回一个计时器ID,您可以使用它取消执行,即在触发超时之前。要取消,您可以这样调用clearInterval或clearTimeout:

var timeoutId = setTimeout(someFunction, 1000);
clearTimeout(timeoutId);
var intervalId = setInterval(someFunction, 1000),
clearInterval(intervalId);

同样,当您离开页面或关闭浏览器窗口时,超时也会自动取消。

您可以在运行以下javascript或检查此JSFiddle时自行验证bobince答案

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

嗯,正如我刚学到的,setTimeout在一种情况下更好。我总是使用setInterval,我已经在后台运行了超过半小时。当我切换回该选项卡时,幻灯片放映(使用了代码的幻灯片)的变化非常快,而不是每5秒更改一次。实际上,随着我对其进行更多测试,它确实会再次发生,并且是否是浏览器的错误并不重要,因为使用setTimeout时,这种情况是完全不可能的。

区别在控制台上很明显:

在此处输入图片说明

只需添加已经说过的内容,但代码的setTimeout版本也将达到,Maximum call stack size这将使其无法运行。由于递归函数没有终止的基本情况,因此您不能使其永远运行

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

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

我认为setTimeout(expression,duration)和setInterval(expression,duration)之间最简单的区别是:-

setTimeout()将在指定的持续时间内仅执行一次表达式。

但是,setInterval()将一次又一次地执行指定的表达式,每次执行都会延迟(两次连续执行之间的时间间隔)指定的持续时间。

我想SetIntervalSetTimeout不同。SetInterval根据设置的时间SetTimeout执行该块,同时执行一次代码块。

在超时倒数秒后尝试以下代码集:

setInterval(function(e){
    alert('Ugbana Kelvin');
}, 2000);

然后尝试

setTimeout(function(e){
    alert('Ugbana Kelvin');
}, 2000);

您可以自己查看差异。

本文地址:http://javascript.askforanswer.com/settimeouthuosetinterval.html
文章标签: ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!