Pregunta

He notado que si configuro el setTimeout durante 1 minuto en el futuro, y luego cambie el tiempo de mi sistema a 5 minutos en el pasado, el setTimeout La función se activará en 6 minutos.

Hice esto es porque quería ver qué sucede durante un cambio de ahorro para el día en el reloj del sistema.

Mi página web de JavaScript usa una setTimeout Funciona para actualizar automáticamente la página cada 5 segundos, y si se produjeran ahorros para la luz del día, la información de la página se congelaría durante una hora. ¿Hay una solución alternativa?

Editar: estoy actualizando la página usando AJAX, no quiero actualizar la página completa.

¿Fue útil?

Solución

Lo que haré es cambiar de abrir una nueva solicitud de AJAX cada 5 segundos para usar Cometa (sondeo largo). Es una mejor opción porque el servidor empujará los nuevos resultados al navegador cada vez que se necesitan, esto puede ser cada 5 segundos en el lado del servidor o cada vez que hay nueva información disponible.

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

Hay otras opciones, como Cometd O APE.

Otros consejos

Usar setInterval en vez de setTimeout y tus problemas deben resolverse :)

Actualizar:

Si realmente no puede usar SetTimeout o SetInterval, podría intentar tener un escondido iframe Eso 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 el evento disparando al servidor a través de Push del servidor. Hay muchas razones para no hacer esto, no menos importante que centralizarías los eventos y los convertirías en una carga para el servidor, pero podría considerarse un último recurso.

Recientemente encontré este problema también. En mi caso, el cambio de tiempo puede causar graves pérdidas financieras, así que tuve que tomarlo en serio.

Algunos antecedentes:

  • IE y Opera manejan los sistemas El tiempo cambia correctamente (sin efectos secundarios para SetTimeOut, SetInterval).
  • FF <4.0 y todo el navegador basado en WebKit no maneja el tiempo de cambio del pasado (exactamente como lo describió). Nota: Sin embargo, los temporizadores en Chrome se detienen solo después de un tiempo ~ 2-60.

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

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 puede notar, reinicio el temporizador y, además, sincronizo el tiempo con el servidor.

Puede usar la actualización de metaetiqueta para hacer esto. Este código actualizarí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 en una hora establecida, y luego, cuando cambia el reloj, el código aún se ejecuta en el momento antes de que cambie el reloj? Solo una suposición, pero tendré que tener eso en cuenta la próxima vez que use SetTimeout.

EDITAR: OK, eso no funcionaría para Ajax Editar nuevamente: esta es una muy buena pregunta. Estoy seguro de que SetTimeOut funciona como dije anteriormente, pero wow, este es un teaser cerebral.

Puedes fallar y hacer un if (Date in range foo) controlar. Básicamente, verifique si la marca de tiempo actual está dentro de los 5 segundos del tiempo de ahorro de verano y luego simplemente actualice la página inmediatamente en lugar de usar setTimeout.

De esta manera, los usuarios obtienen una molestia menor cerca de un cambio de tiempo conocido, pero la página no se congelará durante una hora.

Encontré que usando Window. Performance Me dio resultados más precisos y mantuvo las cosas consistentes cuando cambia el tiempo del sistema.

Utilicé esto como una forma de obtener el tiempo actual dentro de una marca SetInterval para que un temporizador de cuenta regresiva no se vea afectado por un cambio de tiempo del sistema. Lo estaba calculando en función de la cantidad de garrapatas desde un momento determinado para intentar evitar hacer trampa en el temporizador (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);
  });
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top