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>
秘訣は、 setInterval
を使用せず、代わりにループで setTimeout
を使用することです。
setInterval
は、指定したタイミング値を1回読み取り、このタイミングに基づいてスケジュールし、それを忘れます。間隔をmyInterval
のような変数に割り当てた場合、実行できるのはclearInterval(myInterval)
だけです。
setTimeout
はほとんど同じですが、同じ関数を手動でループするために使用できる点が異なります。手動でループすると、タイムアウトするたびにsetTimeout
のタイミングを変更できます。
これが簡単な例です。スライダーを左に動かすとカチカチ音が速くなり、右に動かすと遅くなります。
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
では発生しません。
ドキュメンテーション:
これは私がいつも使用する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