Change setInterval value dynamically
Asked Answered
L

4

15

I want to change interval value of setInterval dynamically. I'm struggling due to presence of a loop in setInterval callback function. I have seen too many questions on stackoverflow. But there is no any solution which can help me. If anyone know answer then please explain with an example. Thank You. Here is my code.

<html>
<head>
    <script type="text/javascript">
        var speed = 10;
        function updateSlider(slideAmount) {
            speed = slideAmount;
        }
        function load() {
            downloadUrl("points.xml", function (data) {
                /* code */
                abc();
            });
            function abc() {
                function track() {
                    /* code */
                    downloadUrl("points.xml", function (data) {
                        var xml = data.responseXML;
                        var points = xml.documentElement.getElementsByTagName("point");
                        var i = 0;
                        setInterval(function () {
                            if (i != points.length) {
                                alert(speed);
                            }
                            i++;
                        }, 100 * speed);
                    });
                }
                track();
            }
        }
        function downloadUrl(url, callback) {
            var request = window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest;
            request.onreadystatechange = function () {
                if (request.readyState == 4) {
                    request.onreadystatechange = doNothing;
                    callback(request, request.status);
                }
            };
            request.open('GET', url, true);
            request.setRequestHeader("Content-type", "text/xml");
            request.send(null);
        }
        function doNothing() {
        }
    </script>
</head>
<body onload="load();">
    <div id="slider">
        5% <input id="slide" type="range" min="1" max="20" step="5" value="10" onchange="updateSlider(this.value)" /> 200%
    </div>
    <div id="chosen">10</div>
</body>

Lactescent answered 9/6, 2015 at 7:23 Comment(2)
Once an interval is set, it cannot be altered but it can be stopped with clearInterval and reset. For your needs, use setTimeout and repeatedly set it again with the changed timeout value.Kobarid
You may want to look into this answerClearcut
U
24

The trick is to not use setInterval, and to use setTimeout in a loop instead.

setInterval reads the timing value you give it once, schedules based on this timing, and forgets about it. The only thing you can do is clearInterval(myInterval) if you've assigned your interval to a variable like myInterval.

setTimeout is much the same, except we can use it to manually loop on the same function. Manually looping allows us to change the timing of setTimeout after each timeout.

Here's a quick example. Moving the slider to the left makes the ticking faster, and to the right, slower.

DEMO

var timing = 250,
    i = 0,
    output = document.getElementById('output');

function loop() {
  i++;
  output.innerHTML = i;
  window.setTimeout(loop, timing);
}

document.querySelector('input[type="range"]').addEventListener('change', function (e) {
  timing = parseInt(this.value);
});

loop();
<input type="range" min="100" max="500" value="250" />
<div id="output"></div>

As a side note: Using this pattern is almost always a better option than using setInterval. setInterval runs the chance that your function execution could take longer than the duration of the interval. This never happens with a looping setTimeout if you call setTimeout last in the function.

Documentation:

Undesigning answered 9/6, 2015 at 7:42 Comment(0)
C
1

This is a version without setInterval i always use:

function timer()
{
    var timer = {
        running: false,
        iv: 5000,
        timeout: false,
        cb : function(){},
        start : function(cb,iv,sd){
            var elm = this;
            clearInterval(this.timeout);
            this.running = true;
            if(cb) this.cb = cb;
            if(iv) this.iv = iv;
            if(sd) elm.execute(elm);
            this.timeout = setTimeout(function(){elm.execute(elm)}, this.iv);
        },
        execute : function(e){
            if(!e.running) return false;
            e.cb();
            e.start();
        },
        stop : function(){
            this.running = false;
        },
        set_interval : function(iv){
            clearInterval(this.timeout);
            this.start(false, iv);
        }
    };
    return timer;
}

Usage:

var timer_1 = new timer();
timer_1.start(function(){
    //magic here
}, 2000, false);

var timer_2 = new timer();
timer_2.start(function(){
    //more magic here
}, 3000, true);

//change the interval
timer_2.set_interval(4000);

//stop the timer
timer_1.stop();

The last parameter of the start function is a boolean if the function needs to be run at 0.

You can also find the script here: https://github.com/Atticweb/smart-interval

Chapiter answered 7/7, 2015 at 11:8 Comment(0)
W
1

For React users:

You can use useInterval from usehooks-ts library

  // The counter
  const [count, setCount] = useState<number>(0)
  // Dynamic delay
  const [delay, setDelay] = useState<number>(1000)
  // ON/OFF
  const [isPlaying, setPlaying] = useState<boolean>(false)

  useInterval(
    () => {
      // Your custom logic here
      setCount(count + 1)
    },
    // Delay in milliseconds or null to stop it
    isPlaying ? delay : null,
  )
Willena answered 24/7 at 10:32 Comment(0)
F
0

Here's another easy way to dynamically update interval.

var intv_sec = 1500; // Initial interval in milliseconds
var speed = 1.5; // Multiplier

function chk_fn(){
  // Your code here
  console.log(intv_sec);
  
  
  // Reset and update interval
  clearInterval(chkh);
  intv_sec = intv_sec*speed;
  chkh = setInterval(chk_fn, intv_sec);
}

var chkh = setInterval(chk_fn, intv_sec);
Fatwitted answered 26/7, 2020 at 11:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.