Modo migliore per ottenere tempo in millisecondi in JavaScript?


141

Esiste un'alternativa in JavaScript per ottenere tempo in millisecondi usando l'oggetto date, o almeno un modo per riutilizzare quell'oggetto, senza dover creare un'istanza di un nuovo oggetto ogni volta che devo ottenere questo valore? Lo sto chiedendo perché sto cercando di creare un semplice motore di gioco in JavaScript e, nel calcolare il "delta frame time", devo creare un nuovo oggetto Date ogni frame. Sebbene non sia troppo preoccupato per le implicazioni in termini di prestazioni di ciò, sto riscontrando alcuni problemi con l'affidabilità dell'ora esatta restituita da questo oggetto.

Ho qualche strano "salto" nell'animazione, all'incirca ogni secondo, e non sono sicuro che questo sia correlato alla Garbage Collection di JavaScript o ad una limitazione dell'oggetto Date quando si aggiorna così velocemente. Se imposto il valore delta su una costante, l'animazione è perfettamente fluida, quindi sono abbastanza sicuro che questo "salto" sia correlato al modo in cui ottengo il tempo.

L'unico codice rilevante che posso fornire è il modo in cui calcolo il delta time:

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

Nel calcolare il movimento / animazione moltiplico un valore costante per il delta time.

Se non c'è modo di evitare di ottenere il tempo in millisecondi usando l'oggetto Date, sarebbe una funzione che incrementa una variabile (essendo il tempo trascorso in millisecondi dall'inizio del gioco) e che viene chiamata usando la funzione SetTimer ad un tasso di una volta ogni millisecondi è un'alternativa efficiente e affidabile?

Modifica: ora ho testato il mio codice in diversi browser e sembra che questo "salto" sia davvero evidente solo in Chrome, non in Firefox. Ma sarebbe comunque bello se esistesse un metodo che funzionasse in entrambi i browser.


5
Un oggetto per frame non
CodesInChaos

2
Riguardo all'animazione che salta ogni secondo, questo potrebbe avere qualcosa a che fare con il fatto che Date.getMillisecondsrestituisce solo i millisecondi nel secondo attuale, cioè da 0 a 999? Non stai usando questa funzione nel tuo esempio, ma forse viene usata da qualche altra parte o su un ramo diverso?
Dan Ross,

2
Il salto è legato ad alcuni strani problemi di risoluzione in millisecondi? Dai documenti di Mozilla : "Quando si utilizza now () per creare timestamp o ID univoci, tenere presente che la risoluzione può essere di 15 millisecondi su Windows". Potrebbe essere correlato al singhiozzo?
Zashu,

1
@zashu è stato tanto tempo fa, quindi non ricordo dettagli specifici per questo esempio. Ma per un'applicazione più recente, quando uso Date.now () non vedo più saltare.
Colin Dumitru,

Risposte:


173

Prova Date.now () .

Il salto è molto probabilmente dovuto alla raccolta dei rifiuti. In genere è possibile evitare la garbage collection riutilizzando le variabili il più possibile, ma non posso dire in particolare quali metodi è possibile utilizzare per ridurre le pause della garbage collection.


1
Ho provato ad usare Date.now (), ma ho ancora gli stessi salti. Quindi ora sono abbastanza certo che non è un problema con la garbage collection, ma piuttosto una limitazione quando si ottengono valori esatti con l'oggetto Date. Come ho detto, la sostituzione del delta time con un valore costante si traduce in animazioni / transizioni fluide, quindi l'unica raccolta di dati inutili che potrebbe accadere è con "new Date" o "Date.now ()" (se questa funzione crea un'istanza dei propri oggetti che Non lo so).
Colin Dumitru,

22
Solo un avvertimento: questo non funziona in IE8 e inferiori
Nick

1
Faccio: / Tutto ciò che voglio è la data in ms. Sembra così complicato per qualcosa di così necessario.
Damien Golding,

5
@Prozi +1 .. IE fa davvero schifo, quando sono in programmazione web non mi interessa davvero di IE, solo Chrome e Firefox ..........
TechLife

3
@TechLife Dovresti anche dare un'idea dei browser Android, Safari e Opera, ma sono d'accordo che IE è un sacco di immondizia. Voglio dire, è così grave che gli Stati
Uniti

49

So che questo è un thread piuttosto vecchio, ma per mantenere le cose aggiornate e più pertinenti, puoi utilizzare la performance.now()funzionalità più accurata per ottenere una tempistica più precisa in 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 */
})();

2
L'ultima alternativa dovrebbe essere proprio Date.nowinvece di un'espressione di funzione anonima
Bergi,

1
Sfortunatamente, inoltre, non funziona nei vecchi stupidi browser. Fortunatamente, ho convinto i miei clienti a pagarmi per il tempo che spreco a sostenere IE7 e IE8.
Michael Scheper,

2
|| function () {return new Date (). getTime ()}
mmm

2
Vale la pena notare che performance.now()dà il tempo monotono, a differenza del tempo da Date. Significa che ogni chiamata successiva è garantita per restituire un valore non inferiore a quello precedente.
utente

48

Per quanto ne so, puoi solo avere tempo con Date .

Date.now è la soluzione ma non è disponibile ovunque: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/now .

var currentTime = +new Date();

Questo ti dà l'ora corrente in millisecondi.

Per i tuoi salti . Se calcoli correttamente le interpolazioni in base al tempo delta del frame e non hai qualche errore di arrotondamento , scommetto per il Garbage Collector (GC).

Se nel loop è presente un sacco di oggetti temporanei creati, la garbage collection deve bloccare il thread per effettuare una pulizia e una riorganizzazione della memoria.

Con Chrome puoi vedere quanto tempo impiega il GC nel pannello Timeline .

EDIT: dalla mia risposta, Date.now()dovrebbe essere considerata l'opzione migliore in quanto è supportata ovunque e su IE> = 9.


4
In quale funzione +serve +new?
Andrew Scagnelli,

33
Il +semplicemente gettato Datea Number, dando un timestamp UNIX standard in millisecondi. Puoi ottenere esplicitamente questo valore chiamando(new Date()).getTime()
ngryman il

9
@mikenelson: Non è terribile per me, questo è ovvio quando sai come funziona la coercizione. Detto questo, Date.now()è preferito ora perché il suo supporto è abbastanza grande ora.
ngryman,

1
Io preferisco solo +che .getTime()... E 'semplice e non ho bisogno di memorizzare i nomi delle funzioni

2
@TravisJ Fantastica scorciatoia? Per recuperare un valore numerico che è già all'interno del tuo computer, crei un oggetto, chiama un operatore che verifica un int e attiva una conversione che chiama una funzione (valueOf) che chiama il metodo di conversione di classe che chiama una funzione (getTime) che infine recupera il valore. Quindi l'oggetto viene abbandonato al suo destino e dopo 1000 iterazioni del loop hai 1000 oggetti Date eliminati che richiedono la raccolta dei rifiuti sospesi lì che all'improvviso vengono scaricati tutti insieme, e mentre il tuo computer è in ritardo ti chiedi cosa sta succedendo. :) Eccezionale!
FrancescoMM,

7

Se hai un oggetto data simile

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

allora c'è un metodo integrato in javascript per ottenere la data in formato millisecondi che è valueOf ()

date.valueOf(); //1512239400000 in milliseconds format

2

Questa è una domanda molto vecchia - ma ancora come riferimento se gli altri la stanno guardando - requestAnimationFrame()è il modo giusto di gestire l'animazione nei browser moderni:

AGGIORNAMENTO: Il link mozilla mostra come farlo - non mi andava di ripetere il testo dietro il link;)


4
Benvenuto in Stack Overflow ! Potresti voler includere una breve spiegazione di ciò requestAnimationFrameche impedisce questo "salto" come descritto nella domanda. Grazie!
Qantas 94 Pesante,

2
Anche con requestAnimationFrame non intendiamo supporre che la frequenza dei fotogrammi sia la stessa su tutte le piattaforme, quindi dobbiamo ancora controllare l'ora corrente.
Tom Boutell,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.