clearTimeout not working: parameter undefined(even though it's defined in the global scope)

微笑、不失礼 提交于 2020-01-16 09:06:50

问题


My setTimeout() function works, but my clearTimeout() is not working. Even though I have an 'if' statement that's supposed to run the clearTimeout function once my variable 'secs' is less than 0, the timer keeps counting down into negative numbers. When I type my variable name, 'secs' into the console, I get undefined, even though it's defined as a parameter in the function called by my setTimeout. I don't know what I'm doing wrong. Can anyone help, please?

My full code is at https://codepen.io/Rburrage/pen/qBEjXmx;

Here's the JavaScript snippet:

function startTimer(secs, elem) {
    t = $(elem);
    t.innerHTML = "00:" + secs;

    if(secs<0) {
        clearTimeout(countDown);
    }
    secs--;
    //recurring function
    countDown = setTimeout('startTimer('+secs+',"'+elem+'")', 1000);

}

回答1:


Add a condition to call recursive function like below.

if (secs < 0) {

   secs = secsInput;
 }

   //recurring function
    countDown = setTimeout('startTimer('+secs+',"'+elem+'")', 1000);



回答2:


For a countdown timer, I would recommend using setInterval and clearInterval instead. setInterval will repeatedly run the callback function for you. It might look like this:

let countdown;

function startTimer(secs, elem) {
  countdown = setInterval(function(){
    t = $(elem);
    t.innerHTML = "00:" + secs;

    secs--
    if (secs < 0) {
      clearInterval(countdown);
    }
  }, 1000);
}



回答3:


By the time you call clearTimeout(countDown), countDown refers to the previous timeout, that already timed out. It will not stop the one yet to start. You could just not re set the timeout, like

 if(!/*finished*/) setTimeout(startTimer, 1000, secs, elem);



回答4:


In your case, it's more convenient to use setInterval and clearInterval.

To keep the setTimeout and clearTimeout functions, you should add return in the if statement.

function startTimer(secs, elem) {
    t = $(elem);
    t.innerHTML = "00:" + secs;

    if(secs<0) {
        clearTimeout(countDown);
        return;
    }
    secs--;
    //recurring function
    countDown = setTimeout('startTimer('+secs+',"'+elem+'")', 1000);

}



回答5:


So there are 4 events in my opinion that will have to be addressed by the timer:

  1. The quiz starts
  2. The quiz ends
  3. The timer runs out
  4. The player answers a question

This can be solved by a function returning an object with some options. The createTimer can be used to set the parameters for the timer.

Point 1. would be timer.start() --> will start a timer with the parameters

Point 3. can be addressed with the callback that will be called if the timer runs out --> createTimer(5,'display', ()=>{ // your code goes here })

Point 2. can be achieved with --> timer.stop()

Point 4. is needed when the timer needs to be reset without running out timer.reset()

Further on the interval is not in the global scope so you could have multiple timers with different settings and they wouldn't interfere with each other

// function for creating the timer
function createTimer(seconds, cssSelector, callbackOnTimeout) {
    // interval the timer is running
    let interval;
    // the html node where innerText will be set
    const display = document.getElementById(cssSelector)
    // original seconds passt to createTimer needed for restart
    const initSec = seconds

    // starting or continuing the interval
    function start() {

        // setting interval to the active interval
        interval = setInterval(() => {

            display.innerText = `00:${seconds}`;

            --seconds;
            if (seconds < 0) {
                // calling restart and callback to restart
                callbackOnTimeout()
                restart()
            }
        }, 1000);

    }

    // just stopping but not resetting so calling start will continue the timer
    // player takes a break
    function stop(){
        clearInterval(interval)
    }

    // opted for a restart and not only a reset since it seemed more appropriate for your problem
    function restart(){
        clearInterval(interval)
        seconds = initSec
        start()
    }
    // returning the object with the functions
    return {
        start: start,
        stop:   stop,
        restart:  restart
    }
}

// example for creating a timer
const timer1 = createTimer(5,'display',()=>{
    console.log(`you where to slow ohhh...`)
})

// calling the timer
timer1.start()


来源:https://stackoverflow.com/questions/59478991/cleartimeout-not-working-parameter-undefinedeven-though-its-defined-in-the-gl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!