【问题标题】:How can I make my setTimout functions run at the same speed?如何使我的 setTimeout 函数以相同的速度运行?
【发布时间】:2012-01-27 14:58:58
【问题描述】:

前言:我的个人网站上有一个demo of the problem(希望没问题。如果没有,我可以尝试在 jsfiddle 上进行设置)。我打算让这个问题变得有趣一点,同时也尝试了解 javascript 中的时间函数。

我在超时时增加进度条的值。理想情况下(如果函数即时运行)它们应该以相同的速度填充,但在现实世界中,它们不会。代码是这样的:

function setProgress(bar, myPer) {
bar.progressbar({ value: myPer })
    .children('.ui-progressbar-value')
        .html(myPer.toPrecision(3) + '%')
            .attr('align', 'center');
    myPer++;
    if(myPer == 100) { myPer = 0; }
 }

 function moveProgress(bar, myPer, inc, delay){
    setProgress(bar, myPer);
    if(myPer >= 100) { myPer = 0; }
    setTimeout(function() { moveProgress(bar, myPer+inc, inc, delay); }, delay);
 }

 $(function() { 
   moveProgress($(".progressBar#bar1"), 0, 1, 500);
   moveProgress($(".progressBar#bar2"), 0, 1, 500);
   moveProgress($(".progressBar#bar3"), 0, .1, 50);
   moveProgress($(".progressBar#bar4"), 0, .01, 5);             
 });

天真地,人们会认为应该以相同的速度运行(填充进度条)。

但是,在前两个条中,(如果我们将“设置进度条”称为单个操作)我每 500 毫秒执行一次操作,总共 500 次操作来填充进度条;第三,我每 50 毫秒执行一次操作,总共 5,000 次操作以填充条形图;在第四个中,我每 5 毫秒执行一次操作,总共 50,000 次操作来填充条形图。

我的代码的哪一部分花费时间最长,会导致这些速度差异,并且可以进行更改以使它们看起来以它们的方式运行(第四条的增量较小),但也可以在速度一样吗?

【问题讨论】:

  • 如果我没看错,您的标签在示例网站上已关闭。第 4 小节不是每 5 毫秒 .01 次吗?
  • @JamesMontagne 哎呀。谢谢。固定。
  • 请注意,setTimeout 调用的延迟可能会限制在最小值; html5 浏览器(和 Chrome)为 4 毫秒,但这取决于浏览器。即它可能会将其限制为更大的值,例如 10 毫秒。

标签: javascript optimization time


【解决方案1】:

setTimeout 用于此类事情的最大问题是您的代码执行发生在超时之间,并且没有计入发送到setTimeout 的值中。如果您的延迟是 5 毫秒,而您的代码需要 5 毫秒来执行,那么您实际上是在加倍时间。

另一个因素是一旦你的超时触发,如果另一段代码已经在执行,它将不得不等待它完成,延迟执行。

这与人们在尝试将setTimeout 用作时钟或秒表时遇到的问题非常相似。解决方案是将当前时间与程序启动的时间进行比较,并据此计算时间。你可以做类似的事情。检查自您开始以来已经过了多长时间,并据此设置百分比。

【讨论】:

  • 啊,所以条形图似乎以固定速率递增,因为它开始以来的时间在增加,但每次都是新的计算,所以它可以弥补排队延迟造成的时间损失和运营?
  • 基本上。您可能会在很短的时间内稍微不同步,但下次触发超时时总是会立即返回。
  • 我意识到这是一种实验性的事情,但如果这是一个真实的情况,您可能只需要一个计时器,并且您会在同一执行中更新所有 4 个计时器。那么你将永远保持同步。
【解决方案2】:

导致速度差异的原因有两点:首先是您执行了更多代码来填充底部栏(正如您在第 2 段到最后一段中提到的那样)。此外,每次您设置超时时,您的浏览器都会将其排队...实际延迟可能比您指定的更长,具体取决于队列中的数量(请参阅MDN on window.setTimeout)。

【讨论】:

    【解决方案3】:

    喜欢这个问题,我没有非常准确的答案,但这是我的 2 美分:

    Javascript 是一种非常快速的语言,可以很好地处理它的事件循环,因此早餐吃 setTimeouts 和 setIntervals。
    但是有一些限制,它们取决于很多因素,例如浏览器和计算机的速度、事件循环中的函数数量、要执行的代码的复杂性和超时值...

    在这种情况下,我认为很明显,如果您尝试每 500 毫秒执行一个函数,它的行为会比每 50 毫秒执行一次要好得多,因此比每 5 毫秒要好得多。如果考虑到将它们全部运行在彼此之上,则可以预测性能不会是最佳的。

    你可以试试这个练习:
    拿 500ms 一个,然后单独运行。标记填充条所需的总时间(在这里您会看到它需要比预期更长的时间)。
    尝试同时执行两个 500 毫秒的超时,看看总时间变长了一点。
    如果将 50ms 添加到它,然后再添加 5ms,您会发现每次都会失去性能...

    【讨论】:

      猜你喜欢
      • 2013-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-30
      • 1970-01-01
      • 1970-01-01
      • 2011-12-03
      • 1970-01-01
      相关资源
      最近更新 更多