1

I am currently building this timer on a webview where the timer will automatically updates with javascript and the timer will decrement every second.

The current problem is that when a user makes the phone go to sleep, the timer doesn't update accordingly and the countdown will be a bit off so I would want to update the timer through server side instead of relying on a function that will break if a user makes the phone go to sleep. Here is the current code that I have

<h2 id="timer"> 
   1:00
<h2>

<script>
   var countdown = new Date("<?php echo $row['end_timer'] ?>").getTime();
   var now = new Date("<?php echo date('Y-m-d H:i:s') ?>")

     var x = setInterval(function() {

         // Increase the distance by 1
         now.setSeconds(now.getSeconds() +                                           

         var distance = countdown - (now.getTime());

         var seconds = Math.floor((distance % (1000 * 60)) / 1000);

          document.getElementById("timer").innerHTML = (seconds < 10 ? '0' : '') + seconds;

          if (distance < 0) {
             clearInterval(x);
             document.getElementById("timer").innerHTML = "00";
             location.reload();
           }
     }, 1000);
</script>
3
  • You can do that but you should not use PHP for that. PHP is designed to run once for a short time (milliseconds). It is possible to keep PHP running for minutes but it has many problems. Node.js would be better fitted for this kind of task. Alternatively you can rewrite your JS code so that it still works if the phone goes to sleep Commented May 6, 2019 at 16:45
  • Re-sync with the server using a single ajax call after the phone wakes? Commented May 6, 2019 at 16:47
  • How do you resync with an ajax call? Commented May 6, 2019 at 16:51

2 Answers 2

1

I can think of three ways to sync the countdown with the server.

  1. Send an AJAX request every second or when the phone wakes
  2. Use Server Sent Events
  3. Use WebSockets

But there is a much simpler way. You can just rewrite your JS. You are adding 1 second to your now variable. But that does not work because setInterval does not call its callback in the specified interval (1000 ms in your case) if the phone is sleeping. So you add one second to now although more than one second has passed.

var countdown = new Date(Date.now()+30*1000) // Countdown will end in 30 sec from now
var cdElem = document.getElementById("coutdown");

function displayCountdown() {
  //Time until the end of the countdown in ms
  var deltaTime = countdown.getTime() - Date.now();
  if(deltaTime < 0) {
    clearInterval(intervalId)
    deltaTime = 0;
  }
  cdElem.innerText = Math.round(deltaTime/1000);
}

var intervalId = setInterval(displayCountdown, 1000);
displayCountdown()
<h1 id="coutdown"></h1>

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the answer! The question I have now is how to set it to a certain timezone. Since the server side is UTC I would need to change javascript to UTC time right?
You can specify the timezone offset if you construct a date like this: new Date('August 19, 1975 23:15:30 GMT-02:00'); or your can use the method .getTimezoneOffset() and do some math
How would you sync javascript time with server time if there's a slight offset?
You can round(microtime(true) * 1000) in PHP and Date.now() in JS to get the number of milliseconds since Jan 1st 1970. Use the difference of both values to adjust your countdown.
0
var countdown = new Date(Date.now() + 3599 * 1000);
var cdElem = document.getElementById("countdown");
var startButton = document.getElementById("start-button");
var intervalId;

function displayCountdown() {
  // Time until the end of the countdown in ms
  var deltaTime = countdown.getTime() - Date.now();
  if (deltaTime < 0) {
    clearInterval(intervalId);
    deltaTime = 0;
  }

  var seconds = Math.floor(deltaTime / 1000) % 60;
  var minutes = Math.floor(deltaTime / 1000 / 60) % 60;
  var formattedTime = padZero(minutes) + ":" + padZero(seconds);
  cdElem.innerText = formattedTime;
}

// Pad the number with a leading zero if it's less than 10
function padZero(number) {
  return number < 10 ? "0" + number : number;
}

function startTimer() {
  intervalId = setInterval(displayCountdown, 1000);
  displayCountdown();
  startButton.disabled = true;
}

startButton.addEventListener("click", startTimer);

1 Comment

make sure you explain your code or answer accordingly. Only a solved code helps in the rarest cases. In the best case you underline your answer with sources that support it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.