Settimeout не работает, когда окно теряет фокус

У меня есть простой хронограф 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). У него очень странное поведение, потому что иногда он работает, иногда нет.

Я видел много постов, в которых требовался скрипт для остановки, когда он не в фокусе, я хочу прямо противоположное и искал более часа, но безуспешно. Ваша помощь очень ценится!


person user2115923    schedule 27.02.2013    source источник
comment
придирка: измените строку setTimeout на setTimeout(display,100), не используйте строки, так как это вызывает дополнительную оценку.   -  person epascarello    schedule 27.02.2013
comment
comment
Chrome автоматически регулирует тайм-ауты и интервалы, когда вкладка не сфокусирована, и я не думаю, что вы можете заставить его делать иначе, но вы можете довольно легко вычислить и компенсировать несоответствия, особенно если вы рассчитываете время. Вместо того, чтобы предполагать, что ваш тайм-аут будет работать в течение следующих 100 мс, сохраните текущее время и сравните его со временем, когда срабатывает тайм-аут.   -  person Mahn    schedule 27.02.2013


Ответы (1)


Тайм-ауты JavaScript не гарантируют выполнение в определенное время. Например, если поток занят чем-то другим в то время, когда таймер заканчивает работу, он сначала завершит то, что он делает, а затем выполнит ваш таймер.

Также ваша функция не учитывает время, проведенное внутри функции отображения, поэтому на каждую миллисекунду будет добавляться небольшая задержка.

Правильный способ реализации таймера — использовать системное время.

Итак, что-то вроде:

//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()
person Boris Marinov    schedule 17.01.2015