JavaScript - setInterval only running once

2019-05-29 20:44发布

问题:

http://jsfiddle.net/689nauny/

setInterval() is only running once... WTF is going on?

SO is asking for more details but providing a JSFiddle is about as descriptive as I can be? I've tried using an anonymous function and now a callback. I just don't get it? :-/

HTML

<script src="http://code.jquery.com/jquery-2.1.3.min.js"></script>

<div id="qanda-timer-container">
    <div class="qanda-timer">
        <span id="qanda-time-remaining"></span>
    </div>
</div>

JS

    function intervalFunc(thinkingTime, answerTime)
    {
        jQuery('#qanda-time-remaining').text(''+(thinkingTime - 1));
    }

    function enableTimer(time)
    {
        var intervalID;
        var hasThinkingTime = true;
        var thinkingTime = time;

        var hasAnswerTime = true;
        var answerTime = 10;

        if(hasThinkingTime && hasAnswerTime)
        {
            setInterval( intervalFunc(thinkingTime, answerTime), 1000);
        }

        setTimeout(function(){ 

            clearInterval(intervalID);

        }, time * 1000);
    }

enableTimer(30);

回答1:

You need to wrap the interval handler in a function:

        intervalId = setInterval( function() { intervalFunc(thinkingTime, answerTime) }, 1000);

Your code as posted is calling the function and passing the result to setInterval(). The interval timer isn't running at all!

After you do that, you'll need to fix the problem of maintaining the descending time value. Currently you pass the variable as a parameter and subtract one from it, but you don't update the original variable.

function intervalFunc(thinkingTime, answerTime)
{
    jQuery('#qanda-time-remaining').text(''+(thinkingTime));
}

Then change the setInterval setup:

    intervalId = setInterval( function() { intervalFunc(--thinkingTime, answerTime) }, 1000);

}


回答2:

Your code doesn't work because of this line:

setInterval( intervalFunc(thinkingTime, answerTime), 1000);

Change it into this:

setInterval( function(){
    intervalFunc(thinkingTime, answerTime);
}, 1000);

You need to provide a function to setInterval(), while you are providing undefined.

This is why it doesn't run.

Running code:

function enableTimer(time)
{
    var elem = jQuery('#qanda-time-remaining'), interval = setInterval( function(){

        if(time/1 == time/1 && time) //if(!isNaN(time) && time>0)
        {
            elem.text( time-- );
        }
        else
        {
            clearInterval(interval);
            elem.text(0);
        }
      
    }, 1000);
}

enableTimer(5);
    <script src="http://code.jquery.com/jquery-2.1.3.min.js"></script>

    <div id="qanda-timer-container">
        <div class="qanda-timer">
            <span id="qanda-time-remaining"></span>
        </div>
    </div>

I have simplified your code to the extreme and is so much easy to read.

You can set a new parameter to which you provide a function that will run after the time is up:

function enableTimer(time, fn)
{
    var elem = jQuery('#qanda-time-remaining'), interval = setInterval( function(){

        if(time/1 == time/1 && time) //if(!isNaN(time) && time>0)
        {
            elem.text( time-- );
        }
        else
        {
            clearInterval(interval);
            elem.text(0);
            if( fn instanceof Function )//if fn is a function
            {
                fn();//call it
            }
        }
      
    }, 1000);
}

enableTimer(5, function(){ alert('Time\'s up!'); });
    <script src="http://code.jquery.com/jquery-2.1.3.min.js"></script>

    <div id="qanda-timer-container">
        <div class="qanda-timer">
            <span id="qanda-time-remaining"></span>
        </div>
    </div>



回答3:

Here is a working example: http://jsfiddle.net/689nauny/3/

Your issue was partly with scope and in general how you decremented the count down variable

var thinkingTime = undefined;
var answerTime = undefined;
var intervalID = undefined;

function enableTimer(time) {

    var hasThinkingTime = true;
    thinkingTime = time;

    var hasAnswerTime = true;
    answerTime = 10;

    if (hasThinkingTime && hasAnswerTime) {
        intervalID = setInterval(function () {
            thinkingTime -= 1;
            jQuery('#qanda-time-remaining').text('' + (thinkingTime));
        }, 1000);
    }

    setTimeout(function () {

        clearInterval(intervalID);

    }, time * 1000);
}

enableTimer(30);