Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

340
Visualizações
¿Cómo crear un temporizador preciso en javascript?

Necesito crear un temporizador simple pero preciso.

Este es mi código:

 var seconds = 0; setInterval(function() { timer.innerHTML = seconds++; }, 1000);

Después de exactamente 3600 segundos, imprime alrededor de 3500 segundos.

  • ¿Por qué no es exacto?

  • ¿Cómo puedo crear un temporizador preciso?

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

¿Por qué no es exacto?

Porque está utilizando setTimeout() o setInterval() . No se puede confiar en ellos, no hay garantías de precisión para ellos. Se les permite retrasarse arbitrariamente y no mantienen un ritmo constante sino que tienden a desviarse (como ha observado).

¿Cómo puedo crear un temporizador preciso?

Utilice el objeto Date en su lugar para obtener la hora actual precisa (en milisegundos). Luego, base su lógica en el valor de tiempo actual, en lugar de contar con qué frecuencia se ha ejecutado su devolución de llamada.

Para un temporizador o reloj simple, realice un seguimiento de la diferencia horaria explícitamente:

 var start = Date.now(); setInterval(function() { var delta = Date.now() - start; // milliseconds elapsed since start … output(Math.floor(delta / 1000)); // in seconds // alternatively just show wall clock time: output(new Date().toUTCString()); }, 1000); // update about every second

Ahora, eso tiene el problema de posiblemente saltar valores. Cuando el intervalo se retrasa un poco y ejecuta su devolución de llamada después de 990 , 1993 , 2996 , 3999 , 5002 milisegundos, verá la segunda cuenta 0 , 1 , 2 , 3 , 5 (!). Por lo tanto, sería recomendable actualizar más a menudo, como cada 100 ms, para evitar tales saltos.

Sin embargo, a veces realmente necesita un intervalo constante para ejecutar sus devoluciones de llamada sin desviarse. Esto requiere una estrategia un poco más avanzada (y código), aunque paga bien (y registra menos tiempos de espera). Esos se conocen como temporizadores autoajustables . Aquí, el retraso exacto para cada uno de los tiempos de espera repetidos se adapta al tiempo realmente transcurrido, en comparación con los intervalos esperados:

 var interval = 1000; // ms var expected = Date.now() + interval; setTimeout(step, interval); function step() { var dt = Date.now() - expected; // the drift (positive for overshooting) if (dt > interval) { // something really bad happened. Maybe the browser (tab) was inactive? // possibly special handling to avoid futile "catch up" run } … // do what is to be done expected += interval; setTimeout(step, Math.max(0, interval - dt)); // take into account drift }
over 4 years ago · Santiago Trujillo Relatório

0

Solo me basaré un poco en la respuesta de Bergi (específicamente la segunda parte) porque realmente me gustó la forma en que se hizo, pero quiero la opción de detener el temporizador una vez que comienza (como clearInterval() casi). Así que... Lo he envuelto en una función de constructor para que podamos hacer cosas 'objetivas' con él.

1. Constructor

Muy bien, entonces copia/pega eso...

 /** * Self-adjusting interval to account for drifting * * @param {function} workFunc Callback containing the work to be done * for each interval * @param {int} interval Interval speed (in milliseconds) * @param {function} errorFunc (Optional) Callback to run if the drift * exceeds interval */ function AdjustingInterval(workFunc, interval, errorFunc) { var that = this; var expected, timeout; this.interval = interval; this.start = function() { expected = Date.now() + this.interval; timeout = setTimeout(step, this.interval); } this.stop = function() { clearTimeout(timeout); } function step() { var drift = Date.now() - expected; if (drift > that.interval) { // You could have some default stuff here too... if (errorFunc) errorFunc(); } workFunc(); expected += that.interval; timeout = setTimeout(step, Math.max(0, that.interval-drift)); } }

2. Instanciar

Dile lo que tiene que hacer y todo eso...

 // For testing purposes, we'll just increment // this and send it out to the console. var justSomeNumber = 0; // Define the work to be done var doWork = function() { console.log(++justSomeNumber); }; // Define what to do if something goes wrong var doError = function() { console.warn('The drift exceeded the interval.'); }; // (The third argument is optional) var ticker = new AdjustingInterval(doWork, 1000, doError);

3. Entonces haz... cosas

 // You can start or stop your timer at will ticker.start(); ticker.stop(); // You can also change the interval while it's in progress ticker.interval = 99;

Quiero decir, funciona para mí de todos modos. Si hay una mejor manera, déjame saber.

over 4 years ago · Santiago Trujillo Relatório

0

La respuesta de Bergi señala exactamente por qué el cronómetro de la pregunta no es preciso. Esta es mi opinión sobre un temporizador JS simple con los métodos start , stop , reset y getTime :

 class Timer { constructor () { this.isRunning = false; this.startTime = 0; this.overallTime = 0; } _getTimeElapsedSinceLastStart () { if (!this.startTime) { return 0; } return Date.now() - this.startTime; } start () { if (this.isRunning) { return console.error('Timer is already running'); } this.isRunning = true; this.startTime = Date.now(); } stop () { if (!this.isRunning) { return console.error('Timer is already stopped'); } this.isRunning = false; this.overallTime = this.overallTime + this._getTimeElapsedSinceLastStart(); } reset () { this.overallTime = 0; if (this.isRunning) { this.startTime = Date.now(); return; } this.startTime = 0; } getTime () { if (!this.startTime) { return 0; } if (this.isRunning) { return this.overallTime + this._getTimeElapsedSinceLastStart(); } return this.overallTime; } } const timer = new Timer(); timer.start(); setInterval(() => { const timeInSeconds = Math.round(timer.getTime() / 1000); document.getElementById('time').innerText = timeInSeconds; }, 100)
 <p>Elapsed time: <span id="time">0</span>s</p>

El fragmento también incluye una solución para su problema. Entonces, en lugar de incrementar la variable de seconds cada intervalo de 1000 ms, simplemente iniciamos el temporizador y luego, cada 100 ms*, simplemente leemos el tiempo transcurrido del temporizador y actualizamos la vista en consecuencia.

* - lo hace más preciso que 1000ms

Para que su cronómetro sea más preciso, tendría que redondear

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda