0

I am new to coding and so my code is a bit messy. So I was in the process of making a 5-minute count-down timer and it does countdown but it appears to either skip some numbers or there seems to be a strange delay. Why is this? Here is the link https://jsfiddle.net/m82ube1y/9/

var timer= document.getElementById("timer").children;
var edDate = new Date();
var endDate = edDate.setMinutes(edDate.getMinutes()+5) ;

setInterval(time, 1000);

function time() {

var currentDate = new Date().getTime();

var countdowntime = endDate-currentDate;

var days = Math.floor((((countdowntime/1000)/60)/60)/24);
var hours = Math.floor((((countdowntime/1000)/60)/60))%24;
var minutes = Math.floor(((countdowntime/1000)/60))%60;
var seconds = Math.floor((countdowntime/1000))%60;
    timer[0].textContent = days;
    timer[1].textContent = hours;
    timer[2].textContent = minutes;
    timer[3].textContent = seconds;

    timer[3].classList.add("rotate");
    setTimeout(function(){f(3);},500);
    function f(x){timer[x].classList.remove("rotate")}

    if(timer[3].textContent==59){ 
        timer[2].classList.add("rotate");
        setTimeout(function(){f(2);},500);}
}

EDIT: I Found out that it works fine in firefox but not in chrome. Still don't get why..

  • https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout#Reasons_for_delays_longer_than_specified – Iłya Bursov Sep 19 '18 at 23:10
  • Where is the *f* function defined? There are many questions on timers already, but one hint is that *setInterval* doesn't necessarily run at exactly the interval you specify, it will usually run slightly (and sometimes greatly) slower, depending on system activity. – RobG Sep 19 '18 at 23:17
  • 1
    Oh, there is no need for all those parenthesis: `Math.floor(countdowntime/1000/60/60/24)` is fine. All the divisions have equal precedence so are evaluated left to right. – RobG Sep 19 '18 at 23:22
  • I Found out that it works fine in firefox but not in chrome. Still don't get why.. – Razib Sarker Sep 19 '18 at 23:22
  • You rely on the interval triggering exactly once every second, [which might not always be the case](https://stackoverflow.com/questions/985670/will-setinterval-drift). Thus, sometimes it might be a second off, but will correct itself in the long run. Instead of calculating the date for each step, you should consider simply decrementing a value by 1 each time and use that instead of calculating `endDate-currentDate` for each step :) – Exfridos Sep 19 '18 at 23:27
  • I slightly changed your code to reflect my above statement :) This should do it https://jsfiddle.net/m82ube1y/22/ – Exfridos Sep 19 '18 at 23:31
  • @Exfridos—much better to use a Date (or *Date.now*) each time since there is no guarantee that the timer will run once per second using either *setTimeout* or *setInterval*. – RobG Sep 20 '18 at 03:44
  • Well my main objective was for the timer to count down with an illusion of approximately every second and so it was not necessary for me for it to be 100% accurate. – Razib Sarker Sep 20 '18 at 09:40
  • @RobG Okay, I might be wrong :) It just feels like such a heavy recurring unnecessary calculation. setInterval might indeed not run exactly once per second, but it will, however, correct itself in the long run, such that if it took 1100 ms for the last update, it will try to force the next update in 900 ms instead. Hence for a timer that runs over 5 minutes, the approach I provided will most likely only be a few milliseconds off, if any at all, after the five minutes. If that's acceptable, then I believe it's the cleanest approach. Check this http://jsfiddle.net/hqmLg/1/ (credit @Phrogz). – Exfridos Sep 20 '18 at 22:57
  • @Exfridos—running *Date.now* once per second is hardly a big ask and likely it's being called anyway. I can't see any evidence of *setInterval* being self–correcting, perhaps it's implementation dependent, but certainly unreliable. On my system a simple log of `(start-end)` lags about 1ms per call, much more if the system is busy. Running something reasonably reliably just after the next full second is as simple as setting the interval to `1020 - Date.now()%1000`. – RobG Sep 21 '18 at 03:30

0 Answers0