简体   繁体   中英

Javascript: restarting countdown timer doesn't work as I expect it to

I am making a countdown timer that should be reseting and starting anew every 10 seconds. This is the code I came up with by now:

function count(){
    var end_date = new Date().getTime()+10*1000;
    setInterval(function(){
      var current_date = new Date().getTime();
      var seconds_left = parseInt((end_date - current_date) / 1000);
      document.getElementById("countdown").innerHTML = seconds_left + " seconds ";
    }, 1000);
}

setInterval(function(){count()}, 10*1000);

It is supposed to function as follows:
+ I set interval that will restart count() every 10 seconds.
+ count() defines end_date - a date 10 seconds from now.
+ then count() sets interval that will restart every 1 second.
+ every 1 second seconds_left variable is changed according to how current_date changed with respect to end_date .
+ as soon as seconds_left becomes 0, setInterval from step 1 fires and starts count() anew.

Which step am I implementing the wrong way? Do I misunderstand the functioning of setInterval() ? Here is my JsFiddle: http://jsfiddle.net/sy5stjun/ .

There are a few things going on, here. You're not specific why you have to set another interval inside your loop, but there are a lot easier ways to accomplish what you're going for. Another approach follows:

HTML:

<!-- string concatenation is expensive in any language. 
     Only update what has to change to optimize -->
<h1 id='countdown'><span id="ct"></span> seconds </h1>

JS:

// For one thing, grabbing a new reference to the 
// dom object each interval is wasteful, and could interfere with
// timing, so get it outside your timer, and store it in a var scoped
// appropriately.
var ct = document.getElementById("ct");
// set your start
var ctStart = 10;
// set your counter to the start
var ctDown = ctStart;

var count = function() {
    // decrement your counter
    ctDown = ctDown - 1;
    // update the DOM
    ct.innerHTML = ctDown;
    // if you get to 0, reset your counter
    if(ctDown == 0) { ctDown = ctStart; }
};

// save a reference to the interval, in case you need to cancel it
// Also, you only need to include a reference to the function you're
// trying to call, here. You don't need to wrap it in an anonymous function
var timer = window.setInterval(count, 1000);

My jsFiddle available for tinkering, here: http://jsfiddle.net/21d7rf6s/

My guess is that each call is in its own new object and you get multiple instances of itself fighting ever 10 seconds.

Using your approach using date objects here is a possible re-write:

var tmr = null;
var time;

function bigInterval() {
    clearInterval(tmr);
    time = (new Date()).valueOf() + (10 * 1000);
    smallInterval();
    tmr = setInterval(smallInterval, 500);
}

function smallInterval() {
    var cur = (new Date()).valueOf();
    var seconds_left = parseInt((time - cur) / 1000);
    document.getElementById("countdown").innerHTML = seconds_left + " seconds";
}

bigInterval();
setInterval(bigInterval, 10*1000);

In the above code I've updated the small timer to be 500ms instead of 1000ms as it won't exactly line up with the system clock at 1000 and you get visual jumps in the numbers.

If exact timing isn't 100% important then here is a possible shorter method:

var t = 10;

setInterval(function() {
    document.getElementById("countdown").innerHTML = t + " seconds";
    t--;
    if (t <= 0) {
        t = 10;
    }
}, 1000);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM