it-swarm.com.de

Chrome: Timeouts / Intervalle in Hintergrundregistern ausgesetzt?

Ich habe die Genauigkeit von setTimeout mit dieser Test getestet. Jetzt ist mir aufgefallen, dass setTimeout (wie erwartet) nicht sehr genau ist, aber für die meisten Geräte nicht dramatisch ungenau. Nun, wenn ich den Test in Chrome) ausführe und ihn in einem Hintergrund-Tab laufen lasse (also zu einem anderen Tab wechseln und dort weiterblättern), zum Test zurückkehren und die Ergebnisse überprüfen (falls das der Fall ist) Test beendet) Sie sind dramatisch verändert. Es sieht so aus, als ob die Timeouts viel langsamer liefen. Getestet in FF4 oder IE9 ist dies nicht aufgetreten.

Es sieht also so aus, als würde Chrome suspendiert oder verlangsamt zumindest die Ausführung von Javascript in einem Tab, der keinen Fokus hat. Konnte im Netz nicht viel zu diesem Thema finden. Das würde bedeuten, dass wir es nicht können Führen Sie Hintergrundaufgaben aus, wie z. B. regelmäßige Überprüfungen auf einem Server mithilfe von XHR-Aufrufen und setInterval (Ich vermute, dass setInterval dasselbe Verhalten aufweist, und schreibe einen Test, wenn ich Zeit habe).

Hat jemand dies angetroffen? Gibt es eine Problemumgehung für diese Aussetzung/Verlangsamung? Würden Sie es einen Bug nennen und sollte ich es als solchen ablegen?

115
KooiInc

Ich habe kürzlich danach gefragt, und es handelt sich um ein beabsichtigtes Verhalten. Wenn ein Tab inaktiv ist, wird die Funktion nur maximal einmal pro Sekunde aufgerufen. Hier ist das Codeänderung .

Vielleicht hilft das: Wie kann ich festlegen, dass setInterval auch funktioniert, wenn ein Tab in Chrome inaktiv ist?

TL; DR: Verwenden Sie Web-Worker .

77
pimvdb

Es gibt eine Lösung für die Verwendung von Web Workern, da diese in einem separaten Prozess ausgeführt und nicht verlangsamt werden

Ich habe ein winziges Skript geschrieben, das ohne Änderungen an Ihrem Code verwendet werden kann - es überschreibt einfach die Funktionen setTimeout, clearTimeout, setInterval, clearInterval

Fügen Sie es einfach vor Ihrem gesamten Code ein

http://github.com/turuslan/HackTimer

21
Ruslan Tushov

Das Abspielen eines ~ leeren Sounds zwingt den Browser, die Leistung beizubehalten - ich habe es entdeckt, nachdem ich diesen Kommentar gelesen habe: Wie JavaScript in Chrome mit normaler Geschwindigkeit ausgeführt wird, auch wenn die Registerkarte nicht aktiv ist ?

Ich benötige eine unbegrenzte Leistung bei Bedarf für ein Browsergame, das WebSockets verwendet. Aus Erfahrung weiß ich, dass die Verwendung von WebSockets keine unbegrenzte Leistung gewährleistet. Tests haben jedoch ergeben, dass das Abspielen einer Audiodatei dies zu gewährleisten scheint

Hier sind 2 leere Audio-Loops, die ich für diesen Zweck erstellt habe. Sie können sie kommerziell frei verwenden: http://adventure.land/sounds/loops/empty_loop_for_js_performance.ogghttp://adventure.land/sounds/loops/empty_loop_for_js_performance.wav

(Sie enthalten -58db Rauschen, -60db funktioniert nicht)

Ich spiele sie auf Anfrage mit 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,
    });
}

Es ist traurig, dass es keine integrierte Methode gibt, mit der die vollständige JavaScript-Leistung standardmäßig aktiviert/deaktiviert werden kann. Crypto Miner können jedoch alle Computerthreads mithilfe von Web Workers ohne Eingabeaufforderung hijacken: |

4
Kaan Soral

Ich habe das Worker-Intervall npm-Paket veröffentlicht, das die Implementierung von Interval und ClearInterval mithilfe von Web-Workern festlegt, um auf inaktiven Registerkarten für Chrome, Firefox und IE weiterarbeiten zu können.

Bei den meisten modernen Browsern (Chrome, Firefox und IE) werden Intervalle (Window-Timer) so eingestellt, dass sie in inaktiven Tabs nicht öfter als einmal pro Sekunde ausgelöst werden.

Weitere Informationen finden Sie unter

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

1
gorkemcnr

Ich habe meinen jQuery-Core auf 1.9.1 aktualisiert und die Intervalldiskrepanz in inaktiven Registerkarten behoben. Ich würde das zuerst versuchen, dann in anderen Code-Überschreibungsoptionen suchen.

1
Carey Estes

hier ist meine Lösung, die die aktuelle Millisekunde abruft und sie mit der Millisekunde vergleicht, in der die Funktion erstellt wurde. Bei Intervall wird die Millisekunde aktualisiert, wenn die Funktion ausgeführt wird. Sie können das Intervall/Timeout auch anhand einer ID erfassen.

<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=0){
    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=0){
    nowMillisInterval[id] = getCurrentMillis();
    interval[id] = setInterval(function(){ var now = getCurrentMillis(); if(now >= (+nowMillisInterval[id] + +millis)){callbackfunction.call(); nowMillisInterval[id] = getCurrentMillis();} }, 10);
}

//usage
setAccurateTimeout(function(){ console.log('test timeout'); }, 1000, 1);

setAccurateInterval(function(){ console.log('test interval'); }, 1000, 1);

</script>
0
SwiftNinjaPro