Chrome: тайм-ауты/интервалы приостановлены на вкладках фона?
Я тестировал точность setTimeout
, используя этот тест. Теперь я заметил, что (как и ожидалось) setTimeout
не очень точен, но для большинства приборов не очень неточно. Теперь, если я запускаю тест в Chrome и позволяю ему работать на вкладке фона (так, перейдя на другую вкладку и просматривая там), вернувшись к тесту и проверив результаты te (если тест закончен), они резко изменены. Похоже, что тайм-ауты работают намного медленнее. Протестировано в FF4 или IE9, этого не произошло.
Итак, похоже, что Chrome приостанавливает или, по крайней мере, замедляет выполнение javascript на вкладке, которая не имеет фокуса. Не удалось найти много в сети по этому вопросу. Это означало бы, что мы не можем запускать фоновые задачи, например, периодически проверять на сервере с помощью XHR-вызовов и setInterval
(я подозреваю, что вижу такое же поведение для setInterval
, будет писать тест, если время со мной).
Кто-нибудь сталкивался с этим? Будет ли там обходной путь для этой приостановки/замедления? Вы бы назвали это ошибкой, и я должен записать ее как таковую?
Ответы
Ответ 1
Я недавно спросил об этом, и это поведение по дизайну. Когда вкладка неактивна, только максимум один раз в секунду вызывается функция. Вот изменение кода.
Возможно, это поможет: как я могу заставить setInterval работать, когда вкладка неактивна в Chrome?
TL; DR: использовать веб-работников.
Ответ 2
Существует решение для использования веб-рабочих, поскольку они запускаются в отдельном процессе и не замедляются.
Я написал маленький script, который можно использовать без изменений в коде - он просто переопределяет функции setTimeout, clearTimeout, setInterval, clearInterval
Просто включите его перед всем своим кодом
http://github.com/turuslan/HackTimer
Ответ 3
Воспроизведение пустого звука заставляет браузер сохранить производительность - я обнаружил его после прочтения этого комментария: Как сделать JavaScript запуститься с нормальной скоростью в Chrome, даже если вкладка не активна?
Мне нужна неограниченная производительность по требованию для браузера, в которой используются WebSockets, поэтому я знаю по опыту, что использование WebSockets не гарантирует неограниченной производительности, но из тестов воспроизведение звукового файла, похоже,
Здесь две пустые звуковые циклы, которые я создал для этой цели, вы можете использовать их свободно, коммерчески: http://adventure.land/sounds/loops/empty_loop_for_js_performance.ogg http://adventure.land/sounds/loops/empty_loop_for_js_performance.wav
(Они включают шум -58db, -60db не работает)
Я воспроизвожу их по запросу пользователя с помощью Howler.js: https://github.com/goldfire/howler.js
function performance_trick()
{
if(sounds.empty) return sounds.empty.play();
sounds.empty = new Howl({
src: ['/sounds/loops/empty_loop_for_js_performance.ogg','/sounds/loops/empty_loop_for_js_performance.wav'],
volume:0.5,
autoplay: true, loop: true,
});
}
Печально, что нет встроенного метода для включения/отключения по умолчанию полного javascript-производительности по умолчанию, однако крипторесурсы могут захватывать все ваши компьютерные потоки с помощью веб-рабочих без каких-либо подсказок: |
Ответ 4
Я обновил ядро jQuery до 1.9.1, и он решил расхождение Interval на неактивных вкладках. Сначала я попробую, а затем просмотрю другие варианты переопределения кода.
Ответ 5
Я выпустил worker-interval пакет npm, который установил setInterval и clearInterval с использованием Web-Workers, чтобы поддерживать и запускать неактивные вкладки для Chrome, Firefox и IE.
Большинство современных браузеров (Chrome, Firefox и IE), интервалы (таймеры окна) зажимаются не чаще одного раза в секунду на неактивных вкладках.
Дополнительную информацию можно найти на странице
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval
https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers#Timeouts_and_intervals
Ответ 6
Вот мое решение, которое получает текущую миллисекунду и сравнивает ее с миллисекундой, в которой была создана функция. для интервала будет обновляться миллисекунда при запуске функции. Вы также можете получить интервал/тайм-аут по идентификатору.
<script>
var nowMillisTimeout = [];
var timeout = [];
var nowMillisInterval = [];
var interval = [];
function getCurrentMillis(){
var d = new Date();
var now = d.getHours()+""+d.getMinutes()+""+d.getSeconds()+""+d.getMilliseconds();
return now;
}
function setAccurateTimeout(callbackfunction, millis, id){
nowMillisTimeout[id] = getCurrentMillis();
timeout[id] = setInterval(function(){ var now = getCurrentMillis(); if(now >= (+nowMillisTimeout[id] + +millis)){callbackfunction.call(); clearInterval(timeout[id]);} }, 10);
}
function setAccurateInterval(callbackfunction, millis, id){
nowMillisInterval[id] = getCurrentMillis();
interval[id] = setInterval(function(){ var now = getCurrentMillis(); if(now >= (+nowMillisInterval[id] + +millis)){callbackfunction.call(); nowMillisInterval[id] = getCurrentMillis();} }, 10);
}
setAccurateTimeout(function(){ console.log('test timeout'); }, 1000, 1);
setAccurateInterval(function(){ console.log('test interval'); }, 1000, 1);
</script>