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>