Как правильно использовать setInterval и clearInterval для переключения между двумя разными функциями?

Для практики я пытаюсь отобразить число, которое увеличивается от 0 до 9, затем уменьшается от 9 до 0 и бесконечно повторяется.

Код, который у меня есть, кажется близким, но на вторая итерация setInterval вызовы моих двух соответствующих функций countUp и countDown кажутся конфликтующими друг с другом, так как отображаемые числа не учитываются в предполагаемом порядке... и затем происходит сбой браузера.

Здесь мой код:

<!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>

person Ian Campbell    schedule 07.05.2012    source источник


Ответы (6)


Вам нужно записать возвращаемое значение из setInterval( ... ) в переменную, так как это ссылка на таймер:

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);
    }
}
person xandercoded    schedule 07.05.2012

@ Клод, ты прав, другое решение, которое я предложил, слишком отличалось от исходного кода. Это еще одно возможное решение с использованием setInterval и функций переключения:

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);
}
person Gerardo Lima    schedule 07.05.2012
comment
Хорошая реализация с замыканием, нравится. - person ChandlerQ; 30.03.2013

clearInterval(this);. Вы не можете этого сделать. Вам нужно сохранить возвращаемое значение из 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);
    }       
}
person Rocket Hazmat    schedule 07.05.2012

попробуй это:

...
<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 ==

person Fabrizio Calderan    schedule 07.05.2012

Есть много способов решить эту проблему, вот мое предложение:

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: безопаснее использовать setTimeout, чем setInteval.

person Gerardo Lima    schedule 07.05.2012
comment
Если бы я писал свой собственный код, я бы предпочел решение, подобное вашему. Но вопрошающий пытается кое-что попрактиковаться, а именно прыгать туда-сюда между двумя разными функциями. Вы так и не ответили на его вопрос. - person Claude; 07.05.2012

    /** 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()

Журнал консоли показывает, что он работает

person Flavio    schedule 01.04.2018
comment
Он отвечает на 3 части вопроса. (1) Как правильно установитьInterval (2) и clearInterval (3) для переключения между двумя разными функциями? - person Flavio; 25.05.2018
comment
Когда счетчик удовлетворяет условию в операторе IF, две разные функции countUp() и countDown() очищают предыдущий интервал, устанавливают новый интервал, который переключается на противоположную функцию подсчета. -- если вы запустите это в узле, он отлично работает. - person Flavio; 25.05.2018