How do I correctly use setInterval and clearInterval to switch between two different functions?
Asked Answered
C

6

15

For practice I am trying to display a number that increments from 0 - 9, then decrements from 9 - 0, and infinitely repeats.

The code that I have so far seems to be close, but upon the second iteration the setInterval calls of my 2 respective functions countUp and countDown seem to be conflicting with each other, as the numbers displayed are not counting in the intended order... and then the browser crashes.

Here is my code:

<!DOCTYPE html>
<html>
    <head>
        <title>Algorithm Test</title>
    </head>

    <body onload = "onloadFunctions();">
        <script type = "text/javascript">
            function onloadFunctions()
            {
                countUp();
                setInterval(countUp, 200);
            }

            var count = 0;
            function countUp()
            {
                document.getElementById("here").innerHTML = count;
                count++;

                if(count == 10)
                {
                    clearInterval(this);
                    countDown();
                    setInterval(countDown, 200);
                }
            }
            function countDown()
            {
                document.getElementById("here").innerHTML = count;
                count--;

                if(count == 0)
                {
                    clearInterval(this);
                    countUp();
                    setInterval(countUp, 200);
                }       
            }
        </script>

        From 0 - 9, up and down:&nbsp;&nbsp;<div id = "here"></div>
    </body>
</html>
Canuck answered 7/5, 2012 at 16:9 Comment(0)
U
27

You need to capture the return value from setInterval( ... ) into a variable as that is the reference to the timer:

var interval;
var count = 0;

function onloadFunctions()
{
    countUp();
    interval = setInterval(countUp, 200);
}

/* ... code ... */

function countUp()
{
    document.getElementById("here").innerHTML = count;
    count++;

    if(count === 10)
    {
        clearInterval(interval);
        countUp();
        interval = setInterval(countUp, 200);
    }
}
Unideaed answered 7/5, 2012 at 16:11 Comment(0)
H
7

@Claude, you are right, the other solution I proposed was too different from original code. This is another possible solution, using setInterval and switching functions:

function onloadFunctions() {
    var count = 0;
    var refId = null;
    var target = document.getElementById("aux");

    var countUp = function() {
        target.innerHTML = count;
        count ++;
        if(count >= 9) {
            window.clearInterval(refId);
            refId = window.setInterval(countDown, 500);
        }
    }

    var countDown = function() {
        target.innerHTML = count;
        count --;
        if(count <= 0) {
            window.clearInterval(refId);
            refId = window.setInterval(countUp, 500);
        }
    }
    refId = window.setInterval(countUp, 500);
}
Harvestman answered 7/5, 2012 at 17:8 Comment(1)
Nice implementation with closure, like it.Intestate
D
4

clearInterval(this);. You can't do that. You need to save the return value from setInterval.

var interval;
function onloadFunctions()
{
    countUp();
    interval = setInterval(countUp, 200);
}

var count = 0;
function countUp()
{
    document.getElementById("here").innerHTML = count;
    count++;

    if(count == 10)
    {
        clearInterval(interval);
        countDown();
        interval = setInterval(countDown, 200);
    }
}
function countDown()
{
    document.getElementById("here").innerHTML = count;
    count--;

    if(count == 0)
    {
        clearInterval(interval);
        countUp();
        interval = setInterval(countUp, 200);
    }       
}
Deniable answered 7/5, 2012 at 16:13 Comment(0)
K
1

try this:

...
<body onload = "onloadFunctions();">

    <script>
        var cup, cdown; // intervals
        var count = 0,
            here  = document.getElementById("here");

        function onloadFunctions() {
            cup = setInterval(countUp, 200);
        }

        function countUp() {
            here.innerHTML = count;
            count++;

            if(count === 10) {
                clearInterval(cup);
                cdown = setInterval(countDown, 200);
            }
        }
        function countDown() {   
            here.innerHTML = count;
            count--;

            if(count === 0) {
                clearInterval(cdown);
                cup = setInterval(countUp, 200);
            }       
        }
    </script>

    From 0 - 9, up and down:&nbsp;&nbsp;<div id = "here"></div>
</body>

you could also create a single reference to #here element. Use always === instead of ==

Kolb answered 7/5, 2012 at 16:15 Comment(0)
H
0

There are many ways to solve this problem, the following is my suggestion:

function onloadFunctions() {
    var count = 0;
    var delta = 1;
    var target = document.getElementById("here");
    var step = function() {
        if(count <= 0) delta =  1;
        if(count >= 9) delta = -1;
        count += delta;
        target.innerHTML = count;
        window.setTimeout(step, 500);
    }
    step ();
}

PS: it's safer to use setTimeout than setInteval.

Harvestman answered 7/5, 2012 at 16:39 Comment(1)
If I was writing my own code, I might prefer a solution such as yours. But, the questioner is trying something for practice -- namely hopping back and forth between two different functions. You didn't actually answer his question.Westbrook
P
0
    /** Tools */
const log = require('ololog').configure({
  locate: false
})

let count = 0
let interval__UP
let interval__DOWN

function countUp () {
  count++
  log.green('countUp(): ', count)

  if (count == 5) {
    clearInterval(interval__UP)
    interval__DOWN = setInterval(function () {
      countDown()
    }, 1000)
  }

}

function countDown () {

  count--
  log.red('countDown(): ', count)

  if (count == 0) {
    clearInterval(interval__DOWN)
    interval__UP = setInterval(function () {
      countUp()
    }, 3000)
  }
}

function start () {
  countUp()
  log.cyan('start()')
  interval__UP = setInterval(function () {
    countUp()
  }, 2000)
}

start()

Console Log shows it's working

Pneumatograph answered 1/4, 2018 at 23:38 Comment(2)
It answers the 3 parts of the question. (1) How do I correctly setInterval (2) and clearInterval (3) to switch between two different functions?Pneumatograph
When the count satisfies the condition in the IF statement the two different functions countUp() and countDown() clear the previous interval, sets a new interval, which switches to the opposite count function. -- if you run this in node it works perfectly.Pneumatograph

© 2022 - 2024 — McMap. All rights reserved.