2013-12-19 58 views
4

这里的再现我能想到的最简单的代码:window.setTimeout行为时,窗口没有焦点

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.(视窗7)

+0

setTimout'的'的最小时间间隔和'setInterval'是[铬] 1000毫秒(https://github.com/adobe/chromium/blob/master/webkit /glue/webkit_constants.h)和[firefox](http://dxr.mozilla.org/mozilla-central/search?tree=mozilla-central&q=DEFAULT_MIN_BACKGROUND_TIMEOUT_VALUE&redirect=true)用于非活动选项卡 – C5H8NNaO4

+0

@ C5H8NNaO4我无法找到答案那里为“我应该怎么看”。我可以强制动画运行,而窗口没有对焦? – Letterman

回答

4

大多数现代浏览器(尤其是在移动设备上)暂停标签失焦,以节省CPU周期的脚本执行(例如,这就是为什么requestAnimationFrame被带到生活)。在超时的情况下,更短的间隔实际上被更改为与浏览器供应商认为合适的不同/更高的值。

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

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

-1

的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); 
0

看到差异: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()