【问题标题】:window.setTimeout behaviour when window not in focus [duplicate]窗口不在焦点时的window.setTimeout行为[重复]
【发布时间】:2014-01-07 23:42:05
【问题描述】:

这是我能想到的最简单的复制代码:

ms = 30; // 1000 ?
num = 1;
function test()
{
    num+=ms;
    document.getElementById('Submit').value = num; // Using native Javascript on purpose
    if (num < 4000)
        window.setTimeout(test, ms);
}
test()

我将 ms(迭代之间的毫秒数)设置为 30,运行脚本并移至浏览器上的不同选项卡。

然后我等待大约 10 秒(脚本应该在 4 秒内完成)并返回到选项卡。

如果我使用 Firefox,我会看到脚本尚未完成,并且数字仍在运行(我猜是从我离开它们的地方恢复)。

这已经够烦了,

但是如果我将ms改为1000并重复上述步骤,当我回到标签页时,我看到脚本确实已经完成了。

(脚本仍然需要 4 秒才能完成)。

也就是说,即使窗口失焦,Firefox 有时也会运行 window.setTimeout,有时则不会。可能取决于持续时间

另一方面,Internet Explorer 不会发生这种情况。

即使选项卡没有聚焦,它也会继续运行脚本。不管我怎么设置ms

  • 这是因为 Firefox 的一些性能考虑吗?

  • 到底发生了什么?

  • 这么基本的东西怎么在浏览器之间是一致的, 现在?

或者,我工作错了吗?这是一种奇怪的编码方式吗?

我只是尝试以延迟的方式重复更改 DOM,而不使用 setInterval(因为我正在更改它自己在旅途中的间隔)。

  • 最重要的是,我应该如何看待这一点?

我不能假设我的用户不会离开标签页。

我希望我的用户可以随意离开页面。

如果一个人离开并在半小时后回来,他/她会在页面上看到不相关的动画,仍在运行。

所有连接到该页面的用户都可以看到其中一些动画。

它们不需要以毫秒为单位进行同步,但只有当用户将选项卡/窗口置于焦点时,我才能启动它们。

我使用的是 Firefox 25.0.1 和 IE 11。(Windows 7)

【问题讨论】:

  • 对于非活动标签,setTimoutsetInterval 的最小间隔为 1000 毫秒,在 chromefirefox
  • @C5H8NNaO4 我在那里找不到“我应该如何看待这个”的答案。我可以在窗口未聚焦时强制运行动画吗?

标签: javascript cross-browser settimeout


【解决方案1】:

查看区别:http://jsfiddle.net/qN6eB/

ms = 30; // 1000 ?
num = 1;
start = new Date();

function test()
{
    num+=ms;
    document.getElementById('Submit').value = num;
    if (num < 4000)
        window.setTimeout(test, ms);
    else
        document.getElementById('Time').value = new Date() - start;
}

test()



ms2 = 30; // 1000 ?
num2 = 1;
start2 = new Date();
dueTo = new Date(+new Date()+4000);

function test2()
{
    num2+=ms2;
    document.getElementById('Submit2').value = num2;
    if (new Date() < dueTo)
        window.setTimeout(test2, ms2);
    else 
        document.getElementById('Time2').value = new Date() - start2;
}
test2()

【讨论】:

    【解决方案2】:

    大多数现代浏览器(尤其是在移动设备上)暂停执行不在焦点的选项卡中的脚本以节省 CPU 周期(例如,这就是启用 requestAnimationFrame 的原因)。在超时的情况下,更短的间隔实际上会更改为浏览器供应商认为合适的不同/更高的值。

    您可以做些什么来克服这个问题(如果您确实必须知道连续执行之间的间隔)是在激活超时时设置时间戳,并将其与实际执行超时处理程序时的时间戳进行比较。请注意,在制作动画时,最好通过考虑其他应用程序变量来计算动画对象的属性,而不是依赖特定处理程序的调用量。

    您还可以将侦听器附加到“(un)focus”事件的窗口,以了解用户何时“返回”到您的应用程序。在此事件处理程序中,您可以验证超时是否挂起并手动执行其回调(如果必须这样做)。

    【讨论】:

      【解决方案3】:

      setTimeout 的计时不精确。因为计时器不会中断进程,所以我会等待空闲时间。我不知道浏览器是如何管理它的,但非活动标签的优先级可能较低。

      我可以考虑两种解决方案: - 尝试 setInterval(我不确定这是否能解决您的问题) - 不要增加变量,而是使用包含开始时间的 Date 对象,并将其与函数执行时的当前时间进行比较。

      var beginTime = (new Date()).getTime();
      var intervalId = setInterval(function() {
          var timePassed = (new Date()).getTime() - beginTime;
          document.getElementById('Submit').value = timePassed;
          if(timePassed >= 4000) {
              clearInterval(intervalId);
          }
      }, 30);
      

      【讨论】:

        猜你喜欢
        • 2012-07-21
        • 2012-08-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多