Domanda

Ho notato che se ho impostato il setTimeout Per 1 minuto in futuro, quindi cambia il tempo del mio sistema a 5 minuti in passato, il setTimeout La funzione si attiverà in 6 minuti.

L'ho fatto è perché volevo vedere cosa succede durante un cambio di risparmio diurno all'orologio del sistema.

La mia pagina web JavaScript utilizza un setTimeout Funzionare per aggiornare automaticamente la pagina ogni 5 secondi e se si verificano risparmi diurni, le informazioni sulla pagina si congelano per un'ora. C'è una soluzione alternativa?

EDIT: sto aggiornando la pagina usando Ajax, non voglio aggiornare l'intera pagina.

È stato utile?

Soluzione

Quello che farò è cambiare dall'apertura di una nuova richiesta AJAX ogni 5 secondi da utilizzare Cometa (sondaggio lungo). È un'opzione migliore perché il server spingerà 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 usare le prese Web e avere cometa come indietro. Questo è facile da implementare con Faye o Socket.oi.

Ci sono altre opzioni, come Cometd O Ape.

Altri suggerimenti

Uso setInterval invece di setTimeout E i tuoi problemi dovrebbero essere risolti :)

Aggiornare:

Se non puoi davvero usare setTimeout o setInterval, potresti provare ad avere un nascosto iframe Questo carica una semplice pagina HTML che assomiglia 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 sei fortunato, il meta aggiornamento non ti causerà gli stessi problemi.

Un'altra soluzione sarebbe quella di spostare l'evento che si lancia sul server tramite Push del server. Ci sono molte ragioni per non farlo, non da ultimo che avresti centralizzato gli eventi e renderli un onere per il server, ma potrebbe essere considerato un'ultima risorsa.

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

Qualche sfondo:

  • IE e Opera gestiscono correttamente i sistemi (nessun effetto collaterale su setTimeout, setInterval).
  • FF <4.0 e tutto il browser basato su WebKit non riescono a gestire il cambiamento di tempo nel passato (esattamente come hai descritto). Nota: i timer in Chrome si fermano solo dopo un po 'di tempo ~ 2-60.

La mia soluzione: utilizzare alcuni eventi dall'interazione dell'utente (cioè MouseMove, Mouseve, ecc.) Per attivare il controllo del cambio di 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 puoi notare, riavvia il timer e sincronizzare inoltre il tempo con il server.

È possibile utilizzare l'aggiornamento del meta tag per farlo. Questo codice aggiornerebbe la pagina ogni 5 secondi:

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

Per quanto riguarda la domanda JavaScript, potrebbe essere solo il modo in cui il browser gestisce il setTimeout. Dice al browser di eseguire il codice in un momento impostato, e poi quando l'orologio cambia, il codice esegue ancora in quel momento prima che il clock è cambiato? Solo un'ipotesi, ma dovrò tenerlo a mente la prossima volta che userò setTimeout.

EDIT: OK, non funzionerebbe di nuovo per Ajax Edit: questa è davvero una buona domanda. Sono sicuro che setTimeout funziona come ho detto sopra, ma wow, questo è un teaser cerebrale.

Puoi fonder e fare un if (Date in range foo) dai un'occhiata. Fondamentalmente controlla se il timestamp corrente è entro 5 secondi dall'ora legale e quindi aggiorna immediatamente la pagina piuttosto che usando setTimeout.

In questo modo gli utenti ottengono un piccolo fastidio vicino a un cambio di tempo noto, ma la pagina non si congela per un'ora.

L'ho trovato usando finestra.performance Mi ha dato risultati più accurati e ha mantenuto le cose coerenti quando il tempo del sistema cambia.

L'ho usato come un modo per ottenere l'ora corrente all'interno di un segno di spunta setInterval in modo che un timer per il conto alla rovescia non sia influenzato da una modifica del tempo di sistema. Lo stavo calcolando in base al numero di zecche da un determinato momento per tentare di impedire che tradisci sul timer (ottenendo più tempo) modificando l'orologio 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);
  });
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top