Meilleur moyen d'obtenir le temps en millisecondes en javascript?


141

Existe-t-il une alternative en JavaScript pour obtenir l'heure en millisecondes en utilisant l'objet date, ou au moins un moyen de réutiliser cet objet, sans avoir à instancier un nouvel objet chaque fois que j'ai besoin d'obtenir cette valeur? Je pose cette question parce que j'essaie de créer un moteur de jeu simple en JavaScript, et lors du calcul du "delta frame time", je dois créer un nouvel objet Date à chaque image. Bien que je ne sois pas trop préoccupé par les implications en termes de performances, j'ai quelques problèmes avec la fiabilité de l'heure exacte renvoyée par cet objet.

J'obtiens un étrange "saut" dans l'animation, toutes les secondes environ, et je ne suis pas sûr si cela est lié à la récupération de place de JavaScript ou à une limitation de l'objet Date lors de la mise à jour si rapide. Si je règle la valeur delta sur une constante, alors l'animation est parfaitement fluide, donc je suis assez sûr que ce "saut" est lié à la façon dont j'obtiens l'heure.

Le seul code pertinent que je puisse donner est la façon dont je calcule le temps delta:

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

Lors du calcul de mouvement / animation, je multiplie une valeur constante par le temps delta.

S'il n'y a aucun moyen d'éviter d'obtenir l'heure en millisecondes en utilisant l'objet Date, une fonction qui incrémente une variable (étant le temps écoulé en millisecondes depuis le début du jeu), et qui est appelée à l'aide de la fonction SetTimer à un taux de une fois toutes les millisecondes une alternative efficace et fiable?

Edit: J'ai testé maintenant mon code dans différents navigateurs et il semble que ce "saut" n'apparaisse vraiment que dans Chrome, pas dans Firefox. Mais ce serait toujours bien s'il y avait une méthode qui fonctionne dans les deux navigateurs.


5
Un objet par image n'est rien
CodesInChaos

2
A propos de l'animation sautant toutes les secondes, cela pourrait-il avoir quelque chose à voir avec le fait que Date.getMillisecondsne renvoie que les millisecondes dans la seconde actuelle, c'est-à-dire de 0 à 999? Vous n'utilisez pas cette fonction dans votre exemple, mais peut-être qu'elle est utilisée ailleurs, ou sur une autre branche?
Dan Ross

2
Le saut est-il lié à des problèmes de résolution étranges en millisecondes? D'après la documentation de Mozilla : "Lorsque vous utilisez now () pour créer des horodatages ou des identifiants uniques, gardez à l'esprit que la résolution peut être de 15 millisecondes sous Windows". Cela pourrait-il être lié au hoquet?
zashu

1
@zashu c'était il y a longtemps, donc je ne me souviens pas de détails pour cet exemple. Mais pour une application plus récente, lors de l'utilisation de Date.now (), je ne vois plus sauter.
Colin Dumitru

Réponses:


173

Essayez Date.now () .

Le saut est probablement dû à la récupération de place. En règle générale, le garbage collection peut être évité en réutilisant autant que possible les variables, mais je ne peux pas dire spécifiquement quelles méthodes vous pouvez utiliser pour réduire les pauses de garbage collection.


1
J'ai essayé d'utiliser Date.now (), mais j'ai toujours les mêmes sauts. Alors maintenant, je suis presque certain que ce n'est pas un problème avec le garbage collection, mais plutôt une limitation lors de l'obtention de valeurs exactes avec l'objet Date. Comme je l'ai dit, le remplacement du temps delta par une valeur constante entraîne des animations / transitions fluides, donc le seul garbage collection qui pourrait se produire est avec "new Date" ou "Date.now ()" (si cette fonction instancie ses propres objets qui Je ne sais pas).
Colin Dumitru

22
Juste un heads - up: Cela ne fonctionne pas dans IE8 et ci - dessous
Nick

1
Je fais: / Tout ce que je veux, c'est la date en ms. Cela semble si compliqué pour quelque chose de si nécessaire.
Damien Golding

5
@Prozi +1 .. IE est vraiment nul, quand je suis en programmation Web, je m'en fous de IE, juste chrome et firefox ..........
TechLife

3
@TechLife Vous devriez également réfléchir aux navigateurs Android, Safari et Opera, mais je conviens que IE est un tas de déchets. Je veux dire que c'est tellement grave que MS ait abandonné et implémente un nouveau navigateur dans W10
Dendromaniac

49

Je sais que c'est un fil assez ancien, mais pour garder les choses à jour et plus pertinentes, vous pouvez utiliser la performance.now()fonctionnalité plus précise pour obtenir un timing plus fin en 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
La dernière alternative devrait être juste Date.nowau lieu d'une expression de fonction anonyme
Bergi

1
Ne fonctionne pas non plus dans les vieux navigateurs stupides, malheureusement. Heureusement, j'ai convaincu mes clients de me payer pour le temps que je perds à supporter IE7 et IE8.
Michael Scheper

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

2
A noter que performance.now()donne le temps monotone, contrairement au temps de Date. Cela signifie que chaque appel suivant est garanti de renvoyer une valeur non inférieure à la précédente.
utilisateur

48

Pour autant que je sache, vous ne pouvez avoir du temps qu'avec Date .

Date.now est la solution mais n'est pas disponible partout: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/now .

var currentTime = +new Date();

Cela vous donne l'heure actuelle en millisecondes.

Pour vos sauts . Si vous calculez correctement les interpolations en fonction du temps de trame delta et que vous n'avez pas d' erreur de nombre d'arrondi , je parie pour le ramasse-miettes (GC).

S'il y a beaucoup d'objets temporaires créés dans votre boucle, le garbage collection doit verrouiller le thread pour effectuer un nettoyage et une réorganisation de la mémoire.

Avec Chrome, vous pouvez voir combien de temps le GC passe dans le panneau Chronologie .

EDIT: Depuis ma réponse, Date.now()devrait être considérée comme la meilleure option car elle est prise en charge partout et sur IE> = 9.


4
Quelle est la fonction de la +servir dans +new?
Andrew Scagnelli

33
Le +cast simplement Datevers Number, donnant un horodatage standard Unix en millisecondes. Vous pouvez explicitement obtenir cette valeur en appelant(new Date()).getTime()
ngryman

9
@mikenelson: Pas terrible pour moi, c'est évident quand on sait comment fonctionne la coercition. Cela dit, Date.now()c'est préféré maintenant car son soutien est assez important maintenant.
ngryman

1
Je préfère juste +que .getTime()... C'est plus simple et je n'ai pas besoin de mémoriser les noms de fonctions

2
@TravisJ Raccourci génial? Pour récupérer une valeur numérique qui se trouve déjà dans votre ordinateur, vous créez un objet, appelez un opérateur qui teste un int et déclenche une conversion qui appelle une fonction (valueOf) qui appelle la méthode de conversion de classe qui appelle une fonction (getTime) qui enfin récupère la valeur. Ensuite, l'objet est abandonné à son destin, et après 1000 itérations de la boucle, vous avez 1000 objets Date supprimés nécessitant un ramasse-miettes qui sont soudainement tous vidés ensemble, et pendant que votre ordinateur est en retard, vous vous demandez ce qui se passe. :) Impressionnant!
FrancescoMM

7

Si vous avez un objet de date comme

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

puis il y a une méthode intégrée en javascript pour obtenir la date au format millisecondes qui est valueOf ()

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

2

C'est une question très ancienne - mais toujours pour référence si d'autres la regardent - requestAnimationFrame()est la bonne façon de gérer l'animation dans les navigateurs modernes:

MISE À JOUR: Le lien mozilla montre comment faire cela - je n'avais pas envie de répéter le texte derrière le lien;)


4
Bienvenue dans Stack Overflow ! Vous voudrez peut-être inclure une brève explication de ce requestAnimationFramequi empêche ce «saut» comme décrit dans la question. Merci!
Qantas 94 Heavy

2
Même avec requestAnimationFrame, nous ne sommes pas censés supposer que la fréquence d'images est la même sur toutes les plates-formes, nous devons donc toujours vérifier l'heure actuelle.
Tom Boutell
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.