javascript setInterval - countdown lagging [closed

2020-07-25 05:30发布

问题:

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 7 years ago.

I use this code below for a countdown in seconds. The problem is that when the part of the page including the countdown is loaded again using jquery .load, the new countdown becomes wrong : at every second, we see fast 2 seconds, like this : 9-8...7-6...5-4... as if it was not synchronised with the clock... See it there : aorbaroquethrash.com/test (for the problem to happen, I have to change song while you're there)

Any idea how I can solve this?

<script type = "text/javascript">
/*author Philip M. 2010*/

var timeInSecs;
var ticker;

function startTimer(secs){
timeInSecs = parseInt(secs)-1;
ticker = setInterval("tick()",1000);   // every second
}

function tick() {
var secs = timeInSecs;
if (secs>0) {
timeInSecs--;
}
else {
clearInterval(ticker); // stop counting at zero
}

document.getElementById("countdown").innerHTML = secs;
} 
startTimer(<?php echo $stream['info']['length'];?>);

</script>

Patrick

回答1:

You should be using the current system time to display or calculate how many seconds have elapsed rather than doing your own count. setInterval() is not guaranteed to be called perfectly on time and you can potentially get accumulating error when you just count yourself and you will display the wrong time if it isn't called on time.

Record the time that you start countingand then on each tick, get the new system time and calculate how much time has elapsed since you started counting with no accumulating error.


Also, please don't pass strings to setInterval(). Pass a real function reference as this prevents scoping issues and other potential problems.


Here's an example of working code for a countdown timer:

var startTime, countAmt, interval;

function now() {
  return ((new Date()).getTime());
}

function tick() {
  var elapsed = now() - startTime;
  var cnt = countAmt - elapsed;
  var elem = document.getElementById("counter");
  if (cnt > 0) {
    elem.innerHTML = Math.round(cnt / 1000);
  } else {
    elem.innerHTML = "0";
    clearInterval(interval);
  }
}

function startTimer(secs) {
  clearInterval(interval);
  document.getElementById("counter").innerHTML = secs;
  countAmt = secs * 1000;
  startTime = now();
  interval = setInterval(tick, 1000);  
}

startTimer(20);

Working demo: http://jsfiddle.net/jfriend00/mxntj/



回答2:

I've added this to the jfriend00 script to get 'minutes:secs' :

function minute(secs){
    minVar = Math.floor(secs/60);
    secs = secs % 60;
    if (secs < 10) {
        secs = "0"+secs;
    }
    return minVar+":"+secs;
}

Added to : elem.innerHTML = minute(Math.round(cnt / 1000)); and document.getElementById("countdown").innerHTML = minute(secs);



回答3:

Thanks to you all.

I needed to do add 'clearInterval(ticker);' at the beginning of function startTimer.