当窗口失去焦点时,Settimeout不起作用。

6

我有一个简单的JavaScript计时器,它会显示在名为“d2”的表单字段上,用于检查某个任务完成所需的时间:

var milisec=0 
var seconds=0
var complemento1=""
document.form1.d2.value='00:00:00' 

function display(){ 
    if (milisec>=9){ 
        milisec=0 
        seconds+=1 
    } 
    else{
        milisec+=1
    }
    complemento1=complemento2=complemento3="";
    if ((seconds%60)<10) complemento1="0";
    if ((Math.floor(seconds/60)%60)<10) complemento2="0";
    if ((Math.floor(seconds/3600))<10) complemento3="0";
    document.form1.d2.value=complemento3+Math.floor(seconds/3600)+":"+complemento2+(Math.floor(seconds/60)%60)+":"+complemento1+(seconds%60)
    setTimeout("display()",100) 
}

问题在于当用户打开新标签或使用其他程序时计时器会停止,然后在窗口再次获得焦点时恢复(使用Chrome)。它的行为非常奇怪,因为有时它有效,有时它无效。
我看到很多帖子都需要一个脚本在失去焦点时停止,而我则想要完全相反的效果,并且已经搜索了一个小时也没有找到解决方案。非常感谢您的帮助!

1
细节问题:将setTimeout行更改为setTimeout(display,100),不要使用字符串,因为它会导致额外的评估。 - epascarello
8
Chrome会在选项卡没有焦点时自动限制超时和间隔时间,我认为你无法强制它进行其他操作,但是你可以很容易地计算并补偿不一致之处,特别是如果你正在计算时间。与其假设你的超时将在接下来的100毫秒内运行,不如保存当前时间并将其与超时触发的时间进行比较。 - Mahn
1个回答

3

JavaScript的计时器不能保证在特定时间执行。例如,如果线程在计时器结束时忙于其他事情,则它将首先完成正在进行的工作,然后执行您的计时器。

此外,您的函数不考虑在display函数内部花费的时间,因此每毫秒都会添加一些延迟。

实现计时器的正确方法是使用系统时间。

因此,可以这样做:

//Call at the beggining to save the start time
var start_time = new Date()

// Compute seconds (does not matter when/how often you call it.) 
var milliseconds_since_start = new Date().valueOf() - start_time 

Date对象还可以将该时间段格式化为时钟:

var m  = new Date(milliseconds_since_start)
m.getMinutes()+":"+m.getSeconds()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接