remove nodejs mdn loop eliminar javascript settimeout system-clock

nodejs - JavaScript setTimeout y los cambios en la hora del sistema causan problemas



settimeout mdn (6)

He notado que si configuro setTimeout para 1 minuto en el futuro, y luego cambio la hora de mi sistema a 5 minutos en el pasado, la función setTimeout se activará en 6 minutos.

Hice esto porque quería ver qué sucede durante un cambio de horario de verano en el reloj del sistema.

Mi página web de JavaScript usa una función setTimeout para actualizar automáticamente la página cada 5 segundos, y si ocurriera el horario de verano, la información de la página se congelaría durante una hora. ¿Hay una solución?

Edición: estoy actualizando la página utilizando Ajax, no quiero actualizar toda la página.


Descubrí que el uso de window.performance me daba resultados más precisos y mantenía las cosas consistentes cuando cambia la hora del sistema.

Utilicé esto como una forma de obtener la hora actual dentro de un tick setInterval para que un temporizador de cuenta regresiva no se vea afectado por un cambio de hora del sistema. Lo estaba calculando en función del número de tics de un momento dado para intentar evitar que el cronómetro hiciera trampa (obtener más tiempo) cambiando el reloj del sistema

getCurrentTime = () => { return window.performance ? performance.timing.navigationStart + performance.now() : Date.now(); } tick() { let now = this.getCurrentTime(); if (this.calibrateTime) { //calibrate with a given server time now -= this.timeCalibration; } const elapsedSeconds = (now - this.startedAt) / 1000; if (elapsedSeconds > this.props.timeLimit + this.props.submitBuffer) { clearInterval(this.interval); this.props.onTimeUp(); } let secondsRemaining = this.props.timeLimit - Math.floor(elapsedSeconds); if (secondsRemaining < 0) secondsRemaining = 0; } startTimer() { if (!this.startedAt) { this.startedAt = Date.now(); } this.setState({ started: true }, () => { this.interval = setInterval(this.tick.bind(this), 500); }); }


Lo que haré es cambiar la apertura de una nueva solicitud de Ajax cada 5 segundos para usar Comet (sondeo largo). Es una opción mejor porque el servidor enviará los nuevos resultados al navegador cada vez que se necesiten, esto puede ser cada 5 segundos en el lado del servidor o cada vez que haya nueva información disponible.

Aún mejor sería usar sockets web y tener Comet como retroceso. Esto es fácil de implementar con Faye o socket.oi .

Hay otras opciones, como CometD o Ape.


Puede fudge y hacer una comprobación if (Date in range foo) . Básicamente, compruebe si la marca de tiempo actual está a 5 segundos del horario de verano y luego actualice la página inmediatamente en lugar de usar setTimeout .

De esta manera, los usuarios obtienen una pequeña molestia cerca de un cambio de hora conocido, pero la página no se congela durante una hora.


Puede utilizar la actualización de la etiqueta meta para hacer esto. Este código refrescaría la página cada 5 segundos:

<meta http-equiv="refresh" content="5">

En cuanto a la pregunta de javascript, podría ser la forma en que el navegador maneja el setTimeout. ¿Le dice al navegador que ejecute el código a una hora determinada, y luego, cuando el reloj cambia, el código aún se ejecuta en el momento antes de que el reloj haya cambiado? Solo una suposición, pero tendré que tener eso en cuenta la próxima vez que use setTimeout.

Edit: Ok, eso no funcionaría para ajax. Edit Again: Esta es una muy buena pregunta. Estoy seguro de que setTimeout funciona como dije anteriormente, pero wow, este es un desafío para la mente.


Recientemente me encontré con este problema también. En mi caso, el cambio de horario podría causar graves pérdidas financieras, por lo que tuve que tomarlo en serio.

Algunos antecedentes:

  • IE y Opera manejan el cambio de hora de los sistemas correctamente (sin efectos secundarios para setTimeout, setInterval).
  • FF <4.0 y todos los navegadores basados ​​en Webkit no logran manejar el cambio del tiempo al pasado (exactamente como lo describió). Nota: los temporizadores en Chrome, sin embargo, se detienen solo después de algún tiempo ~ 2-60s.

Mi solución: use algún evento de la interacción del usuario (es decir, mousemove, mouseove, etc.) para activar la verificación de cambio de hora.

Clock.prototype.checkLocalTime = function(){ var diff = Date.now()- this.lastTimestamp; if ( diff < 0 || diff > 20000) { // if time shifted back or more than 20s to the future console.warn(''System time changed! By '' + diff + ''ms'' ); this.restartTimer(); this.getServerTime(); } this.lastTimestamp = time;

}

Como se puede observar, reinicio el temporizador y además sincronizo el tiempo con el servidor.


Use setInterval lugar de setTimeout y sus problemas deberían resolverse :)

Actualizar:

Si realmente no puedes usar setTimeout o setInterval, podrías intentar tener un iframe oculto que carga una página HTML simple que se parece a esto:

<html> <head> <meta http-equiv="refresh" content="300"/> <script> document.domain=''same as parent page''; top.ajax_function_you_wish_to_trigger(); </script> </head> <body> </body> </html>

Si tiene suerte, la meta actualización no le causará los mismos problemas.

Otra solución sería mover la activación de eventos al servidor a través de la inserción del servidor . Hay muchas razones para no hacer esto, entre otras cosas, porque centralizaría los eventos y los convertiría en una carga para el servidor, pero podría considerarse un último recurso.