78 votes

Existe-t-il un moyen plus précis de créer un minuteur Javascript que setTimeout?

Quelque chose qui m'a toujours ennuyé est la façon imprévisible de la setTimeout() méthode en Javascript.

Dans mon expérience, la minuterie est horriblement inexactes dans beaucoup de situations. Par inexactes, je veux dire le délai réel le temps semble varier de 250 à 500 ms plus ou moins. Bien que ce n'est pas une énorme quantité de temps, lorsque vous l'utilisez pour afficher/masquer les éléments de l'INTERFACE utilisateur à la fois peut être visible.

Sont il des trucs qui peut être fait pour s'assurer que setTimeout() effectue avec précision (sans avoir recours à une API externe) ou est-ce une cause perdue?

80voto

Shog9 Points 82052

Sont il des trucs qui peut être fait pour s'assurer que setTimeout()effectue précision (sans avoir recours à un API externe) ou est-ce une cause perdue?

Non et non. Vous n'allez pas pour obtenir quelque chose de proche de un parfaitement exacte de la minuterie avec setTimeout() - les navigateurs ne sont pas mis en place pour cela. Cependant, vous n'avez pas besoin de compter sur elle pour le calendrier de choses. La plupart d'animation des bibliothèques compris cela il y a des années: vous mettez en place un callback avec setTimeout(), mais de déterminer ce qui doit être fait sur la base de la valeur de (new Date()).milliseconds (ou l'équivalent). Cela vous permet de profiter de la plus fiable de la minuterie de support dans les navigateurs les plus récents, tout en continuant à se comporter de manière appropriée sur les navigateurs plus anciens.

Il permet également d' éviter d'utiliser trop de minuteries! Ceci est important: chaque horloge est un rappel. Chaque rappel exécute du code JS. Tout code JS est en cours d'exécution, le navigateur d'événements, y compris d'autres rappels - sont retardés ou supprimés. Lorsque le rappel de finitions, d'autres rappels doit rivaliser avec d'autres événements de navigateur pour avoir une chance de s'exécuter. Par conséquent, une minuterie qui gère toutes les tâches en attente pour cet intervalle sera de faire mieux que les deux horloges avec coïncidant intervalles, et (pour les courts délais d'attente) mieux que deux minuteries avec chevauchement des délais d'attente!

Résumé: arrêtez d'utiliser setTimeout() à mettre en œuvre "une minuterie / une tâche" de dessins, et d'utiliser l'horloge en temps réel afin de lisser les actions d'INTERFACE utilisateur.

36voto

user1213320 Points 203

.

REF; http://www.sitepoint.com/creating-accurate-timers-in-javascript/

Ce site écopé moi sur une grande échelle.

Vous pouvez utiliser l'horloge du système pour compenser la minuterie de l'inexactitude. Si vous exécutez une fonction de synchronisation comme une série de setTimeout appels - chaque instance d'appeler le prochain - alors tout ce que vous avez à faire pour le garder précis, c'est exactement la façon dont il est inexact, et de soustraire cette différence à partir de l'itération suivante:

var start = new Date().getTime(),  
    time = 0,  
    elapsed = '0.0';  
function instance()  
{  
    time += 100;  
    elapsed = Math.floor(time / 100) / 10;  
    if(Math.round(elapsed) == elapsed) { elapsed += '.0'; }  
    document.title = elapsed;  
    var diff = (new Date().getTime() - start) - time;  
    window.setTimeout(instance, (100 - diff));  
}  
window.setTimeout(instance, 100);  

Cette méthode permettra de réduire au minimum la dérive et de réduire les imprécisions par plus de 90%.

Il fixe mes questions, j'espère que ça aide

11voto

Chris GW Green Points 266

J'ai eu un problème similaire il n'y a pas si longtemps et j'ai mis au point une approche associant rAF et performance.now (), qui fonctionne très efficacement.

Je suis maintenant capable de faire des minuteries précises à environ 12 décimales:

     window.performance = window.performance || {};
    performance.now = (function() {
        return performance.now       ||
            performance.mozNow    ||
            performance.msNow     ||
            performance.oNow      ||
            performance.webkitNow ||
                function() {
                    //Doh! Crap browser!
                    return new Date().getTime(); 
                };
        })();
 

http://jsfiddle.net/CGWGreen/9pg9L/

5voto

manast Points 86

Si vous devez obtenir un rappel précis sur un intervalle donné, cet élément essentiel peut vous aider:

https://gist.github.com/1185904

4voto

matt lohkamp Points 1135

shog9 la réponse est à peu près ce que je dis, bien que je serais ajouter ce qui suit à propos de l'INTERFACE utilisateur et d'animation d'événements:

Si vous avez une boîte qui est censé le faire glisser sur l'écran, s'étendent vers le bas, puis fondu dans son contenu, n'essayez pas de faire tous les trois événements distincts avec des délais programmée pour faire le feu l'un après l'autre - utilisez des rappels, donc une fois que le premier événement est terminé le faisant glisser les appels de l'expanseur, une fois cela fait, elle appelle le fader. jQuery pouvez le faire facilement, et je suis sûr que d'autres bibliothèques peuvent ainsi.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X