javascript 动态更改 setInterval 值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30725455/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 12:37:22  来源:igfitidea点击:

Change setInterval value dynamically

javascriptcallbacksetinterval

提问by Akshay Vaghasiya

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.

我想动态更改 setInterval 的间隔值。由于 setInterval 回调函数中存在循环,我很挣扎。我在stackoverflow上看到了太多问题。但是没有任何解决方案可以帮助我。如果有人知道答案,请举例说明。谢谢。这是我的代码。

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

回答by Oka

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

诀窍是不要使用setInterval,setTimeout而是在循环中使用。

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

setInterval读取一次你给它的时间值,根据这个时间安排,然后忘记它。您唯一能做的就是clearInterval(myInterval)将您的时间间隔分配给像myInterval.

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

setTimeout大同小异,只是我们可以用它来手动循环同一个函数。手动循环允许我们更改setTimeout每次超时后的时间。

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

这是一个快速示例。将滑块向左移动会使滴答声更快,向右移动则更慢。

DEMO

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 almostalways a better option than using setInterval. setIntervalruns the chance that your function execution could take longer than the duration of the interval. This never happens with a looping setTimeoutif you call setTimeoutlast in the function.

附带说明:使用这种模式几乎总是比使用setInterval. setInterval运行您的函数执行时间可能比间隔持续时间更长的机会。setTimeout如果您setTimeout在函数中调用last ,则循环永远不会发生这种情况。

Documentation:

文档:

回答by Jaapze

This is a version without setInterval i always use:

这是我一直使用的没有 setInterval 的版本:

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.

如果函数需要在 0 处运行,则 start 函数的最后一个参数是一个布尔值。

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

你也可以在这里找到脚本:https: //github.com/Atticweb/smart-interval