web-dev-qa-db-ja.com

setInterval値を動的に変更する

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

秘訣は、 setInterval を使用せず、代わりにループで setTimeout を使用することです。

setIntervalは、指定したタイミング値を1回読み取り、このタイミングに基づいてスケジュールし、それを忘れます。間隔をmyIntervalのような変数に割り当てた場合、実行できるのはclearInterval(myInterval)だけです。

setTimeoutはほとんど同じですが、同じ関数を手動でループするために使用できる点が異なります。手動でループすると、タイムアウトするたびにsetTimeoutのタイミングを変更できます。

これが簡単な例です。スライダーを左に動かすとカチカチ音が速くなり、右に動かすと遅くなります。

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>

補足として:このパターンを使用することは、ほとんど常にsetIntervalを使用するよりも優れたオプションです。 setIntervalは、関数の実行に間隔の期間よりも長くかかる可能性があります。関数の最後でsetTimeoutを呼び出した場合、これはループsetTimeoutでは発生しません。

ドキュメンテーション:

15
Oka

これは私がいつも使用する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;
}

使用法:

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

関数を0で実行する必要がある場合、start関数の最後のパラメーターはブール値です。

スクリプトはここにもあります: https://github.com/Atticweb/smart-interval

1
Jaapze