javascript setInterval - countdown lagging [closed

2020-07-25 05:19发布

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

3条回答
狗以群分
2楼-- · 2020-07-25 06:00

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/

查看更多
疯言疯语
3楼-- · 2020-07-25 06:11

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);

查看更多
家丑人穷心不美
4楼-- · 2020-07-25 06:12

Thanks to you all.

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

查看更多
登录 后发表回答