Lepszy sposób na uzyskanie czasu w milisekundach w javascript?

141

Czy istnieje w JavaScript alternatywa pobierania czasu w milisekundach przy użyciu obiektu daty lub przynajmniej sposób na ponowne użycie tego obiektu bez konieczności tworzenia wystąpienia nowego obiektu za każdym razem, gdy potrzebuję uzyskać tę wartość? Pytam o to, ponieważ staram się stworzyć prosty silnik gry w JavaScript, a przy obliczaniu "czasu klatki delta" muszę tworzyć nowy obiekt Date w każdej klatce. Chociaż nie martwię się o wpływ tego na wydajność, mam pewne problemy z wiarygodnością dokładnego czasu zwracanego przez ten obiekt.

W animacji pojawiają się dziwne „skoki” w animacji, mniej więcej co sekundę, i nie jestem pewien, czy jest to związane z funkcją Garbage Collection w JavaScript, czy też z ograniczeniem obiektu Date przy tak szybkiej aktualizacji. Jeśli ustawię wartość delta na jakąś stałą, animacja będzie idealnie gładka, więc jestem prawie pewien, że to „przeskakiwanie” jest związane ze sposobem, w jaki odbieram czas.

Jedyny odpowiedni kod, jaki mogę podać, to sposób, w jaki obliczam czas delta:

prevTime = curTime;
curTime = (new Date()).getTime();
deltaTime = curTime - prevTime;

Obliczając ruch / animację mnożę stałą wartość przez czas delta.

Jeśli nie ma sposobu, aby uniknąć uzyskiwania czasu w milisekundach za pomocą obiektu Date, czy funkcja, która zwiększa zmienną (będącą czasem, który upłynął w milisekundach od rozpoczęcia gry) i która jest wywoływana za pomocą funkcji SetTimer z szybkością raz na milisekundy być wydajną i niezawodną alternatywą?

Edycja: Przetestowałem teraz mój kod w różnych przeglądarkach i wygląda na to, że ten „skok” jest tak naprawdę widoczny tylko w Chrome, a nie w Firefoksie. Ale nadal byłoby miło, gdyby istniała metoda, która działa w obu przeglądarkach.

Colin Dumitru
źródło
5
Jeden obiekt na klatkę to nic
CodesInChaos
2
Jeśli chodzi o animację skaczącą co sekundę, czy może to mieć coś wspólnego z faktem, że Date.getMillisecondszwraca tylko milisekundy w bieżącej sekundzie, czyli od 0 do 999? Nie używasz tej funkcji w swoim przykładzie, ale może jest używana w innym miejscu lub w innej gałęzi?
Dan Ross,
2
Czy przeskakiwanie jest związane z dziwnymi problemami z rozdzielczością w milisekundach? Z dokumentacji Mozilli : „Używając funkcji now () do tworzenia znaczników czasu lub unikalnych identyfikatorów, pamiętaj, że rozdzielczość może wynosić 15 milisekund w systemie Windows”. Czy to może być związane z czkawką?
zashu
1
@zashu to było dawno temu, więc nie pamiętam żadnych szczegółów na ten przykład. Ale dla nowszych aplikacji, kiedy używam Date.now (), nie widzę więcej skoków.
Colin Dumitru,

Odpowiedzi:

173

Spróbuj Date.now () .

Pomijanie jest najprawdopodobniej spowodowane usuwaniem elementów bezużytecznych. Zwykle czyszczenia pamięci można uniknąć, ponownie wykorzystując zmienne tak często, jak to możliwe, ale nie mogę powiedzieć konkretnie, jakich metod można użyć, aby skrócić przerwy w usuwaniu pamięci.

Joeri Sebrechts
źródło
1
Próbowałem użyć Date.now (), ale nadal mam te same skoki. Więc teraz jestem prawie pewien, że nie jest to problem z usuwaniem elementów bezużytecznych, ale raczej ograniczenie podczas uzyskiwania dokładnych wartości za pomocą obiektu Date. Tak jak powiedziałem, zastąpienie czasu delta stałą wartością skutkuje płynnymi animacjami / przejściami, więc jedyne wyrzucanie elementów bezużytecznych, które może mieć miejsce, to „nowa data” lub „Date.now ()” (jeśli ta funkcja tworzy instancję własnych obiektów, Nie wiem o czym).
Colin Dumitru
22
Tylko jedno ostrzeżenie: to nie działa w IE8 i starszych
Nick
1
Robię: / Wszystko czego chcę to data w ms. Wydaje się to skomplikowane dla czegoś tak potrzebnego.
Damien Golding
5
@Prozi +1 .. IE naprawdę jest do bani, kiedy programuję w sieci, naprawdę nie obchodzi mnie IE, tylko Chrome i Firefox ..........
TechLife
3
@TechLife Powinieneś także dać do myślenia przeglądarkom z Androidem, Safari i operą, ale zgadzam się, że IE to kupa śmieci. Chodzi mi o to, że jest tak źle, że MS zrezygnowało i wdraża nową przeglądarkę w W10
Dendromaniac
49

Wiem, że to dość stary wątek, ale aby zachować aktualność i trafność, możesz użyć dokładniejszej performance.now()funkcji, aby uzyskać dokładniejsze synchronizowanie ziarna w javascript.

window.performance = window.performance || {};
performance.now = (function() {
    return performance.now       ||
        performance.mozNow    ||
        performance.msNow     ||
        performance.oNow      ||
        performance.webkitNow ||            
        Date.now  /*none found - fallback to browser default */
})();
Chris GW Green
źródło
2
Ostatnią alternatywą powinno być po prostu Date.nowzamiast anonimowego wyrażenia funkcyjnego
Bergi
1
Niestety nie działa też w głupich starych przeglądarkach. Na szczęście przekonałem swoich klientów, aby zapłacili mi za czas, który tracę na obsłudze IE7 i IE8.
Michael Scheper
2
|| function () {return new Date (). getTime ()}
mmm
2
Warto zauważyć, że performance.now()podaje czas monotoniczny, w przeciwieństwie do czasu od Date. Oznacza to, że każde kolejne wywołanie gwarantuje zwrócenie wartości nie mniejszej niż poprzednie.
użytkownik
48

O ile wiem, tylko z Date możesz znaleźć czas .

Date.now jest rozwiązaniem, ale nie jest dostępne wszędzie: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/now .

var currentTime = +new Date();

To daje aktualny czas w milisekundach.

Do Twoich skoków . Jeśli poprawnie obliczysz interpolacje zgodnie z czasem ramki delta i nie masz błędu zaokrąglenia liczby , stawiam na garbage collector (GC).

Jeśli w pętli jest dużo utworzonych tymczasowych obiektów, proces czyszczenia pamięci musi zablokować wątek, aby wykonać pewne porządki i reorganizację pamięci.

W Chrome możesz zobaczyć, ile czasu spędza GC w panelu Oś czasu .

EDYCJA: Ponieważ moja odpowiedź, Date.now()powinna być uważana za najlepszą opcję, ponieważ jest obsługiwana wszędzie i na IE> = 9.

ngryman
źródło
4
Co robi funkcja +służyć w +new?
Andrew Scagnelli
33
Po +prostu rzut Datena Number, dając standardowy znacznik czasu unixa w milisekundach. Możesz bezpośrednio uzyskać tę wartość dzwoniąc(new Date()).getTime()
ngryman
9
@mikenelson: Nie jest to dla mnie straszne, jest to oczywiste, gdy wiesz, jak Date.now()działa przymus. To powiedziawszy, jest teraz preferowane, ponieważ jego wsparcie jest teraz wystarczająco duże.
ngryman
1
Wolę tylko +niż .getTime()... To prostsze i nie potrzebuję zapamiętywać nazw funkcji
2
@TravisJ Niesamowity skrót? Aby pobrać wartość liczbową, która jest już w komputerze, tworzysz obiekt, wywołaj operatora, który testuje int i wyzwala konwersję, która wywołuje funkcję (valueOf), która wywołuje metodę konwersji klasy, która wywołuje funkcję (getTime), która ostatecznie pobiera wartość. Następnie obiekt zostaje porzucony, a po 1000 iteracjach pętli masz 1000 usuniętych obiektów Date wymagających wiszących tam śmieci, które nagle zostają zrzucone razem, a gdy komputer pozostaje w tyle, zastanawiasz się, co się dzieje. :) Niesamowite!
FrancescoMM
7

Jeśli masz obiekt daty, taki jak

var date = new Date('2017/12/03');

to jest wbudowana metoda w javascript do pobierania daty w formacie milisekund, która jest valueOf ()

date.valueOf(); //1512239400000 in milliseconds format
dilip kumar
źródło
2

To bardzo stare pytanie - ale nadal w celach informacyjnych, jeśli inni na nie patrzą - requestAnimationFrame()to właściwy sposób obsługi animacji w nowoczesnych przeglądarkach:

AKTUALIZACJA: Link do Mozilli pokazuje, jak to zrobić - nie miałem ochoty powtarzać tekstu za linkiem;)

LarsKnudsen
źródło
4
Witamy w Stack Overflow ! Możesz chcieć dołączyć krótkie wyjaśnienie, co requestAnimationFramepowoduje powstrzymanie tego „przeskakiwania”, jak opisano w pytaniu. Dzięki!
Qantas 94 Heavy
2
Nawet w przypadku requestAnimationFrame nie mamy zakładać, że liczba klatek na sekundę jest taka sama na wszystkich platformach, więc nadal musimy sprawdzać aktualny czas.
Tom Boutell