Testowałem dokładność setTimeout
użycia tego testu . Teraz zauważyłem, że (zgodnie z oczekiwaniami) setTimeout
nie jest zbyt dokładny, ale w przypadku większości urządzeń nie jest dramatycznie niedokładny. Teraz, jeśli uruchomię test w Chrome i pozwolę mu działać na karcie w tle (więc przełączam się na inną kartę i przeglądam tam), wracam do testu i sprawdzam wyniki (jeśli test się skończył), są dramatycznie zmieniane. Wygląda na to, że limity czasu są znacznie wolniejsze. Testowane w FF4 lub IE9 to nie wystąpiło.
Wygląda więc na to, że Chrome zawiesza lub przynajmniej spowalnia wykonywanie javascript na karcie, która nie jest aktywna. Nie udało się znaleźć w sieci zbyt wielu informacji na ten temat. Oznaczałoby to, że nie możemy uruchamiać zadań w tle, takich jak na przykład okresowe sprawdzanie na serwerze za pomocą wywołań XHR i setInterval
(podejrzewam, że widzę to samo zachowanie setInterval
, napiszę test, jeśli czas jest ze mną).
Czy ktoś to spotkał? Czy byłoby jakieś obejście tego zawieszenia / spowolnienia? Czy nazwałbyś to błędem i czy powinienem to zgłosić jako taki?
źródło
transition
, więc nie wszystkie elementy div przechodzą w tym samym czasie, ale w rzeczywistości 15 ms po sobie, tworząc efekt toczenia. Kiedy przechodzę do innej karty i wracam po chwili, wszystkie elementy div zmieniają się w tym samym czasie isetTimeOut
jest całkowicie ignorowany. Nie jest to duży problem dla mojego projektu, ale jest to dziwny i niechciany dodatek.Odpowiedzi:
Niedawno o to zapytałem i jest to zachowanie zgodne z projektem. Gdy karta jest nieaktywna, wywoływana jest funkcja maksymalnie raz na sekundę. Oto zmiana kodu .
Być może to pomoże: Jak sprawić, by setInterval działał również, gdy karta jest nieaktywna w Chrome?
TL; DR: użyj Web Workers .
źródło
Istnieje rozwiązanie do korzystania z Web Workerów, ponieważ działają one w oddzielnym procesie i nie są spowalniane
Napisałem mały skrypt, którego można używać bez zmian w kodzie - po prostu zastępuje funkcje setTimeout, clearTimeout, setInterval, clearInterval
Po prostu dołącz go przed całym kodem
http://github.com/turuslan/HackTimer
źródło
new Worker('data:text/javascript,(' + function myWorkerCode () { /*...*/ } + '()')
. Jest to również dobry sposób na sprawdzenie, czy masz obsługę wyrażeń importu:try { eval('import("data:text/javascript,void 0")') } catch (e) { /* no support! */ }
Odtwarzanie ~ pustego dźwięku zmusza przeglądarkę do zachowania wydajności - odkryłem to po przeczytaniu tego komentarza: Jak sprawić, by JavaScript działał z normalną prędkością w Chrome, nawet gdy karta nie jest aktywna?
Potrzebuję nieograniczonej wydajności na żądanie dla gry przeglądarkowej korzystającej z WebSockets, więc wiem z doświadczenia, że korzystanie z WebSockets nie zapewnia nieograniczonej wydajności, ale z testów wydaje się, że odtwarzanie pliku audio to zapewnia
Oto 2 puste pętle audio, które utworzyłem w tym celu, możesz z nich swobodnie korzystać komercyjnie: http://adventure.land/sounds/loops/empty_loop_for_js_performance.ogg http://adventure.land/sounds/loops/empty_loop_for_js_performance.wav
(Obejmują hałas -58db, -60db nie działa)
Gram w nie na żądanie użytkownika z 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, }); }
To smutne, że nie ma wbudowanej metody domyślnie włączającej / wyłączającej pełną wydajność javascript, jednak kopacze kryptowalut mogą przejąć wszystkie wątki obliczeniowe przy użyciu narzędzi sieciowych bez żadnego monitu: |
źródło
Wydałem pakiet work -interval npm, który implementuje setInterval i clearInterval z wykorzystaniem Web-Workers do utrzymania i działania na nieaktywnych kartach dla Chrome, Firefox i IE.
W większości nowoczesnych przeglądarek (Chrome, Firefox i IE) interwały (liczniki czasu okien) są uruchamiane nie częściej niż raz na sekundę w nieaktywnych kartach.
Możesz znaleźć więcej informacji na temat
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
źródło
Zaktualizowałem mój rdzeń jQuery do wersji 1.9.1 i rozwiązałem problem rozbieżności interwałów w nieaktywnych zakładkach. Najpierw spróbuję tego, a potem przyjrzę się innym opcjom nadpisywania kodu.
źródło
oto moje rozwiązanie, które pobiera bieżącą milisekundę i porównuje ją z milisekundą, w której funkcja została utworzona. przez interwał zaktualizuje milisekundę, gdy uruchomi funkcję. możesz również pobrać interwał / limit czasu za pomocą identyfikatora.
<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>
źródło