2011-02-02 16 views
20

Ho notato che se imposto lo setTimeout per 1 minuto in futuro e poi cambio il mio sistema su 5 minuti in passato, la funzione setTimeout si innescherà in 6 minuti .JavaScript setTimeout e modifiche all'ora di sistema causano problemi

Ho fatto questo perché volevo vedere cosa succede durante una modifica dell'ora legale all'ora del sistema.

La mia pagina Web JavaScript utilizza la funzione setTimeout per aggiornare automaticamente la pagina ogni 5 secondi e, se l'ora legale dovesse verificarsi, le informazioni sulla pagina si congelerebbero per un'ora. C'è una soluzione?

Modifica: sto aggiornando la pagina utilizzando Ajax, non desidero aggiornare l'intera pagina.

+0

Quale browser stai utilizzando? –

+8

Quando si verifica una modifica dell'ora legale, in realtà si tratta di una modifica dell'offset del fuso orario, non di una modifica all'ora UTC. Il test che hai eseguito non modella ciò che accade realmente se l'ora legale viene gestita automaticamente dal sistema. [Leap seconds] (http://en.wikipedia.org/wiki/Leap_second) potrebbe ancora rappresentare un problema, tuttavia, come sarebbe una sincronizzazione automatica dell'ora se l'orologio del computer si fosse allontanato molto dal tempo reale (quindi non sarebbe gradualmente cambiare il tempo). – PleaseStand

+0

Ho appena provato questo in IE7, IE8, IE9, Firefox e Chrome su Windows 7 e non vedo il comportamento che descrivi. Forse questo è specifico per il sistema operativo? – gilly3

risposta

4

Quello che farò è cambiare dall'aprire una nuova richiesta Ajax ogni 5 secondi per utilizzare Comet (polling lungo). È un'opzione migliore perché il server invierà i nuovi risultati al browser ogni volta che sono necessari, questo può essere ogni 5 secondi sul lato server o ogni volta che sono disponibili nuove informazioni.

Ancora meglio sarebbe utilizzare le prese di rete e avere Comet come back-back. È facile da implementare con Faye o socket.oi.

Ci sono altre opzioni, come CometD o Ape.

+0

+1 per websockets. – Raynos

0

È possibile utilizzare l'aggiornamento del metatag per farlo. Questo codice dovrebbe aggiornare la pagina ogni 5 secondi:

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

quanto riguarda la questione javascript, potrebbe essere solo il modo in cui il browser gestisce il setTimeout. Indica al browser di eseguire il codice a un orario prestabilito, e quindi quando l'orologio cambia, il codice viene ancora eseguito nel momento in cui il cronometro è cambiato? Solo una supposizione, ma dovrò tenerlo a mente la prossima volta che uso setTimeout.

Modifica: Ok, non funzionerebbe per ajax Modifica ancora: Questa è davvero una buona domanda. Sono sicuro che setTimeout funzioni come ho detto sopra, ma wow, questo è un rompicapo.

+0

Ho modificato la mia domanda per aggiungere che sto usando Ajax per aggiornare la pagina e non posso aggiornarla. –

4

Uso setInterval invece di setTimeout e vostri problemi dovrebbero essere risolti :)

Aggiornamento:

Se davvero non si può utilizzare sia setTimeout o setInterval, si potrebbe cercare di avere un nascosta iframe che carica un semplice HTML pagina simile a questa:

<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> 

Se siete fortunati, il meta refresh non causerà gli stessi problemi.

Un'altra soluzione sarebbe spostare l'evento che si attiva sul server tramite server push. Ci sono molte ragioni per non farlo, non meno importante per centralizzare gli eventi e renderli un onere per il server, ma potrebbe essere considerato l'ultima risorsa.

+0

Sfortunatamente questo non risolve questo problema. La stessa cosa succede –

+0

Sfortunatamente setInterval è significativamente peggio. – Raynos

+0

Questo è strano - quale sistema operativo stai? Non riesco a riprodurre questo problema con setInterval su win7 64 bit in qualsiasi browser. –

0

È possibile fondere e fare un controllo if (Date in range foo). In pratica, controlla se la data/ora corrente è entro 5 secondi dall'ora legale e poi aggiorna subito la pagina piuttosto che usando setTimeout.

In questo modo gli utenti ottengono un fastidio minore in prossimità di un cambio orario noto ma la pagina non si blocca per un'ora.

1

Recentemente ho riscontrato anche questo problema. Nel mio caso il cambio di orario potrebbe causare gravi perdite finanziarie, quindi ho dovuto prenderlo sul serio.

Alcuni retroscena:

  • IE e Opera gestisce il cambiamento dei sistemi tempo corretto (senza effetti collaterali a setTimeout, setInterval).
  • FF < 4.0 e tutto il browser basato su Webkit non riesce a gestire il tempo passato al passato (esattamente come descritto). Nota: i timer in Chrome tuttavia si fermano solo dopo un po 'di tempo ~ 2-60s.

La mia soluzione: utilizzare alcuni eventi dell'interazione dell'utente (ad es. Mousemove, mouseove, ecc.) Per attivare il controllo del tempo.

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; 

}

Come potete notare ho riavviato il timer e inoltre sincronizzare l'ora con il server.