1

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);
An0nC0d3r
  • 1,275
  • 13
  • 33
  • 1
    This is because you are calling `clearInterval(intervalID);`. – Ismael Miguel Mar 03 '15 at 16:46
  • But that shouldn't happend for 30 seconds given the example.... – An0nC0d3r Mar 03 '15 at 16:46
  • Different problem: you never assign `intervalID`. – Barmar Mar 03 '15 at 16:47
  • Yes, but that should just be undefined. I have declared it as a var. That shouldn't be causing this issue? – An0nC0d3r Mar 03 '15 at 16:48
  • Since you've mentioned it in your question - Questions (and answers) on Stack Overflow are preferred to be complete by themselves. By all means add links to jsfiddles etc to help demonstrate the problem, but in theory your question should be answerable without having to leave this site - that's why it's prompting you for code. – James Thorpe Mar 03 '15 at 16:49

3 Answers3

8

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

}
Pointy
  • 405,095
  • 59
  • 585
  • 614
  • 2
    @AdamJeffers - its running multiple times in that update, you're not decrementing the number so every time the setInterval runs you get the same output – Jamiec Mar 03 '15 at 16:49
  • The original variable should remain the same... It's the total amount of time. Every second, I'm just taking 1 away from that...? Or am I missing something?? – An0nC0d3r Mar 03 '15 at 16:50
  • @AdamJeffers The function call passes the value of `thinkingTime` to your other function, but subtracting 1 from it only changes that copy - the original value was unchanged. In my updated answer, I predecrement the value in the main function instead, so that it will be affected. – Pointy Mar 03 '15 at 16:51
  • @AdamJeffers also you can add code to that anonymous function to check for `thinkingTime` being zero, and cancel the timer (and `return`) when that happens; that way you won't need the other timer. – Pointy Mar 03 '15 at 16:55
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>
Ismael Miguel
  • 4,185
  • 1
  • 31
  • 42
0

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);
eyegropram
  • 672
  • 4
  • 11