2013-03-29 11 views
5

Sto lavorando su un'applicazione web molto sensibile al tempo. Una delle regole aziendali che mi è stata data è che il comportamento dell'applicazione deve sempre dipendere dall'ora sul server Web, indipendentemente dall'ora in cui si trova l'orologio del client. Per rendere questo chiaro all'utente, mi è stato chiesto di mostrare l'ora del server nell'applicazione web.Visualizzazione dell'ora di un altro computer su una pagina Web utilizzando Javascript?

A tal fine, ho scritto il seguente codice JavaScript:

clock = (function() { 
var hours, minutes, seconds; 

function setupClock(updateDisplayCallback) { 
    getTimeAsync(getTimeCallback); 

    function getTimeCallback(p_hours, p_minutes, p_seconds) { 
     hours = p_hours; 
     minutes = p_minutes; 
     seconds = p_seconds; 
     setInterval(incrementSecondsAndDisplay, 1000); 
    } 

    function incrementSecondsAndDisplay() { 
     seconds++; 
     if (seconds === 60) { 
      seconds = 0; 
      minutes++; 
      if (minutes === 60) { 
       minutes = 0; 
       hours++; 
       if (hours === 24) { 
        hours = 0; 
       } 
      } 
     } 
     updateDisplayCallback(hours, minutes, seconds); 
    } 
} 

// a function that makes an AJAX call and invokes callback, passing hours, minutes, and seconds. 
function getTimeAsync(callback) { 
    $.ajax({ 
     type: "POST", 
     url: "Default.aspx/GetLocalTime", 
     contentType: "application/json; charset=utf-8", 
     dataType: "json", 
     success: function (response) { 
      var date, serverHours, serverMinutes, serverSeconds; 
      date = GetDateFromResponse(response); 
      serverHours = date.getHours(); 
      serverMinutes = date.getMinutes(); 
      serverSeconds = date.getSeconds(); 
      callback(serverHours, serverMinutes, serverSeconds); 
     }  
    }) 
} 

return { 
    setup: setupClock 
}; 
})(); 

La funzione passata per updateDisplayCallback è una semplice funzione per visualizzare la data sulla pagina web.

L'idea di base è che il Javascript effettua una chiamata asincrona per cercare il tempo del server, memorizzare sul client, e quindi aggiornarla una volta al secondo.

In un primo momento, questo sembra funzionare, ma col passare del tempo, il tempo visualizzato si mette dietro un paio di secondi ogni minuto. L'ho lasciato in funzione da un giorno all'altro, e quando sono arrivato la mattina dopo, è stato spento per più di un'ora! Questo è del tutto inaccettabile perché l'applicazione web può essere mantenuta aperta per giorni alla volta.

Come posso modificare il codice in modo che il browser visualizzerà continuamente e con precisione l'ora del server?

+0

Sarebbe un'opzione per effettuare la chiamata ajax una volta ogni minuto o così, per la sincronizzazione con il server? –

+0

tieni presente che la richiesta al server richiede tempo, pertanto devi aggiungere diverse centinaia di ms ogni volta che effettui una chiamata. – charlietfl

+0

setInterval NON È ACCURATO. Fai la differenza dal tempo del server e dall'ora sull'orologio del computer. Aggiungi questa differenza all'orologio dell'utente. Ricorda anche che la latenza delle chiamate HTTP può causare un notevole dispendio di tempo. Ci vuole tempo per viaggiare con le valvole. – epascarello

risposta

0

Grazie per le risposte. Ho votato entrambe le risposte fino a quando contengono informazioni utili. Tuttavia, non sto utilizzando la risposta esatta prescritta in nessuna delle due risposte.

Quello che ho finalmente deciso è un po 'diverso.

Ho scritto quello che ho imparato sul mio personal web page.

Prima di tutto, ora capisco che l'utilizzo di setInterval(..., 1000) non è sufficiente per fare qualcosa una volta al secondo per un lungo periodo. Tuttavia, "sondare" il tempo con un intervallo molto più breve in cerca del secondo a cambiare sembra molto inefficiente per me.

Ho deciso che è opportuno tenere traccia dello "scostamento" tra l'ora del server e l'ora del client.

La mia soluzione finale è quello di effettuare le seguenti operazioni:

(1) Se una chiamata AJAX al server per ottenere il tempo. La funzione controlla anche l'ora del client e calcola la differenza tra l'ora del server e l'ora del client, in millisecondi. A causa della latenza della rete e di altri fattori, questo recupero iniziale potrebbe essere disattivato di alcuni secondi. Per i miei scopi, va bene.

(2) Esecuzione di una funzione tick. Ogni volta che tick viene eseguito, controlla quanto tempo è trascorso dall'ultima volta eseguita tick. Utilizzerà questo tempo per calcolare un argomento da passare a setTimeout in modo che la visualizzazione dell'ora venga aggiornata approssimativamente una volta al secondo.

(3) Ogni volta che la funzione tick calcola il tempo da visualizzare, richiede tempo al client e aggiunge la differenza calcolata nel passaggio (1). In questo modo, non dipendo dal client per impostare correttamente l'ora, ma dipende dal fatto che il cliente calcoli accuratamente il tempo trascorso. Per i miei scopi, va bene. La cosa più importante è che, indipendentemente dal modo in cui setTimeout può essere inaccurato o interrotto da altri processi (ad esempio una finestra di dialogo modale, ad esempio), l'ora visualizzata dovrebbe sempre essere accurata.

+0

Non dimenticare che l'ora dell'utente potrebbe saltare inaspettatamente. Questo potrebbe essere avviato manualmente dall'utente, da un client NTP o a causa di una modifica del fuso orario/ora legale. Supponendo che almeno alcuni utenti non si trovino nella stessa posizione del server, l'ultimo è particolarmente problematico poiché l'ora cambia di un grande incremento. È anche più probabile che accada poiché la tua app è di lunga durata. Fortunatamente, è anche risolvibile senza effettuare chiamate server aggiuntive semplicemente usando getTimezoneOffset() oltre a getTime(). – jerry

2

setInterval non è un modo affidabile per pianificare eventi critici di tempo. Potrebbero essere necessari meno o più di 1000ms per eseguire la richiamata, a seconda di quanto JavaScript sia occupato al momento.

Un approccio migliore sarebbe di prendere un intervallo più breve e utilizzare new Date().getTime() per verificare se un secondo è passato.

I browser minime intervallo permettono è così alta 10.

+0

Ci sono numerose pagine Web che visualizzano il tempo, quindi sembra che ci dovrebbe essere una buona pratica per questo. –

+0

Non ci vorrà mai meno tempo di quanto specificato. Inoltre, l'intervallo minimo non è 10ms. Dipende dal browser. –

+1

Vorrei calibrare ogni minuto per evitare problemi indipendentemente dal metodo utilizzato. –

6

setInterval di Javascript non è sufficientemente preciso per consentire di mantenere l'ora in questo modo.

mia soluzione sarebbe:

  1. periodicamente ottenere il tempo del server in millisecondi (non ha bisogno di essere molto spesso i due orologi difficilmente discostarsi più di tanto)
  2. ottenere il tempo cliente in millisecondi
  3. calcolare la deviazione orologio tra server e client (client-server)
  4. aggiornare periodicamente il display dell'orologio ottenendo l'ora del client e aggiungendo l'orologio deviazione

Modifica: Per essere più precisi, è possibile misurare il tempo di andata e ritorno della richiesta del server, dividerlo per 2 e considerare tale ritardo nella deviazione orologio. Supponendo che i viaggi di andata e ritorno siano simmetrici nella loro durata, ciò darebbe un calcolo più accurato.

+0

1. ... MA il tempo per la richiesta HTTP Ajax per il server sarà molto diverso tra le chiamate in base al traffico di rete. – epascarello

+0

Questa sembra essere una soluzione molto più elegante, dal momento che significa che non si sta scrivendo il proprio orologio in "incrementSecondsAndDisplay()", ma piuttosto si sta utilizzando il 'Date' incorporato nel client. –

+0

@epascarello si utilizzerà l'ora del client quando la risposta del server arriva, ovviamente, non quando la richiesta viene inviata. –

Problemi correlati