D0NDI
D0NDI

Reputation: 13

JavaScript Asynchronous Clock from Server Time Stamp

Currently, I am using an XMLHTTPRequest to get the time and date from an Apache server. The code below shows that...

$(document).ready(function() {
    $("#loadtime").load("getdatetime.php");
    setInterval(function() {
        $("#loadtime").load('getdatetime.php?randval=' + Math.random());
    }, 1000);
    $.ajaxSetup({cache: false});
});

Obviously I do not want to send an http request every second. Below is some code that I am experimenting with.

function getTime() {
    var hr = new XMLHttpRequest();
    var url = "getdatetime.php";
    var myRandom = parseInt(Math.random() * 999999999);

    hr.open("GET", url + "?rand=" + myRandom, true);
    hr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

    hr.onreadystatechange = function() {
        if (hr.readyState === 4 && hr.status === 200) {
            var serverTimeStamp = hr.responseText;
            var displayTime = Date(serverTimeStamp);

            document.getElementById("clock").innerHTML = displayTime;
        }
    };
    hr.send(null);
    return false;
}

The function above grabs a PHP time stamp via PHP built-in time() function that returns the number of seconds since the UNIX epoch. The PHP time stamp can be conveniently placed inside JavaScript's Date() function. So now I am able to return the server's time via HTTP request. The goal is to send one HTTP request every 5mins, instead of every second. So every 5mins I need to grab the Apache time stamp and then iterate on that time stamp...

// Sudo code:
// serverTimeStamp += 1000 (milliseconds)
// iterate on serverTimeStamp for 5mins
// send new HTTP request to get current Apache time stamp
// restart iteration, etc...

I have already discovered that I have no clue how to iterate upon serverTimeStamp asynchronously. I need the clock to iterate in real time and then sync back up with the server every 5mins. How can this be done? I have done some research on Google but I cannot find a simple explanation, just custom functions and references to Node.js, which I am not using. Any help or suggestions would be much appreciated.

Upvotes: 1

Views: 1455

Answers (2)

jwatts1980
jwatts1980

Reputation: 7356

My approach is that you can use the local time to keep track of the milliseconds between syncs. Then you can add those milliseconds to the last server time. So there is a 1 second timer that adds the mills since the last sync to the time that is retrieved from the server every 5 minutes.

Using the milliseconds seems like the best option here because it is a constant metric between both the server time and the JavaScript time. Plus it is easy to set/get with .setTime(mills) and .getTime().

I wrote this in jQuery because you were using it for your AJAX example. I'll work on rewriting it in pure JS, but here is the jQuery version:

<script>
    $(document).ready(function() {
        var jsTime = (new Date()).getTime();
        var serverTime = (new Date()).getTime();

        var getServerTime = function() {
            $.get('getdatetime.php?randval=' + Math.random(), function(data) {
                serverTime = (new Date(data)).getTime(); //set the milliseconds from the server
                jsTime = (new Date()).getTime(); //set the JS mills for reference
            });
        };

        var setTime = function() {
            var currentTime = (new Date()).getTime(); //get the JS mills now
            var mills = serverTime + (currentTime - jsTime); //add the number of mills since the last sync
            var newServerTime = (new Date()).setTime(mills); //create the new adjusted sync time
            $("#loadtime").html(newServerTime); //set the value
        };

        getServerTime(); //sync now
        setInterval(getServerTime, 5*60*1000); //sync every 5 minutes
        setTime(); //set now
        setInterval(setTime, 1000); //set every second

        $.ajaxSetup({cache: false});
    });
</script>

Here it is in pure JS

window.onload = function() {
    var serverTime = (new Date()).getTime();
    var jsTime = (new Date()).getTime();

    var getServerTime = function() {
        var hr = new XMLHttpRequest();
        var url = "getdatetime.php";
        var myRandom = parseInt(Math.random() * 999999999);

        hr.open("GET", url + "?rand=" + myRandom, true);
        hr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

        hr.onreadystatechange = function() {
            if (hr.readyState === 4 && hr.status === 200) {
                serverTime = (new Date(hr.responseText)).getTime(); //set the milliseconds from the server
                jsTime = (new Date()).getTime(); //set the JS mills for reference
            }
        };
        hr.send(null);
    };

    var setTime = function() {
        var currentTime = (new Date()).getTime(); //get the JS mills now
        var mills = serverTime + (currentTime - jsTime); //add the number of mills since the last sync
        var newServerTime = (new Date()).setTime(mills); //create the new adjusted sync time
        document.getElementById("clock").innerHtml = newServerTime; //set the value
    };

    getServerTime(); //sync now
    setInterval(getServerTime, 5*60*1000); //sync every 5 minutes
    setTime(); //set now
    setInterval(setTime, 1000); //set every second
};

Upvotes: 1

Adarsh Rajput
Adarsh Rajput

Reputation: 1276

In first method you can just change second parameter of function 'setInterval' from 1000 to 5*60*1000 coz this is the delay in millisecond. now it will fetch time in every 5 min.

setInterval(function() {
    $("#loadtime").load('getdatetime.php?randval=' + Math.random());
}, 5*60*1000);

According to the comment of @jwatts1980 UPDATE:

var serverTimeStamp=0;
var url = "getdatetime.php";
var clock;

$(document).ready(function() {
   getTime();
}

function startIteration(){
   var after5min=serverTimeStamp+300000;  //300000 = 5*60*1000

   clock=setInterval(function() {
     serverTimeStamp+=1000;
     //-------------
     if(serverTimeStamp >= iteration){
        clearInterval(clock); //to end the iteration
        getTime(); //initiate new request
     }
   }, 1000);
}

function getTime(){
   var myRandom = parseInt(Math.random() * 999999999);

   var hr = new XMLHttpRequest();
   hr.open("GET", url + "?rand=" + myRandom, true);
   hr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

   hr.onreadystatechange = function() {
      if (hr.readyState === 4 && hr.status === 200) {
          serverTimeStamp = hr.responseText;
          var displayTime = Date(serverTimeStamp);
          document.getElementById("clock").innerHTML = displayTime;

          startIteration(); // restart iteration for 5 min OR etc...
      }
   };
   hr.send(null);
}

Upvotes: 0

Related Questions