web-dev-qa-db-ja.com

setTimeoutまたはsetInterval

私が言える限りでは、これら2つのJavaScriptは同じように動作します。

オプションA:

function myTimeoutFunction()
{
    doStuff();
    setTimeout(myTimeoutFunction, 1000);
}

myTimeoutFunction();

オプションB:

function myTimeoutFunction()
{
    doStuff();
}

myTimeoutFunction();
setInterval(myTimeoutFunction, 1000);

setTimeoutsetInterval の使用に違いはありますか?

720
Damovisa

彼らは本質的に同じことをやろうとします、しかしsetIntervalアプローチはsetTimeoutアプローチより正確です、なぜならsetTimeoutは1000msを待って、関数を実行して、そして次に別のタイムアウトを設定するからです。そのため、実際には待機時間は1000msより少し長くなります(関数の実行に時間がかかる場合はもっと長くなります)。

setIntervalは1000msごとに 正確に を実行すると考える人もいるかもしれませんが、JavaScriptはマルチスレッド言語ではないため、setIntervalも遅れることに注意することが重要です。スクリプトの実行中 - インターバルはそれが完了するのを待つ必要があります。

this Fiddle では、タイムアウトが遅れることがわかりますが、間隔はほぼ1コール/秒(スクリプトが実行しようとしています)でほぼ常に一定です。上部の速度変数を20のような小さい値に変更すると(1秒間に50回実行しようとします)、間隔は1秒間に平均50回の反復に達することはありません。

遅延はほとんど無視できますが、本当に正確なものをプログラミングしているのであれば、自己調整タイマー(本質的には作成された遅延を常に調整するタイムアウトベースのタイマー)を選ぶべきです。 )

627

違いはありますか?

はい。タイムアウトは、setTimeout()が呼び出された後、一定時間実行されます。前のインターバルが開始された後、インターバルは一定時間実行されます。

DoStuff()関数の実行にしばらく時間がかかると、違いがわかります。たとえば、setTimeout/setIntervalを.で、timeout/intervalを*で、JavaScriptコードを[-----]でそれぞれ実行すると、タイムラインは次のようになります。

Timeout:

.    *  .    *  .    *  .    *  .
     [--]    [--]    [--]    [--]

Interval:

.    *    *    *    *    *    *
     [--] [--] [--] [--] [--] [--]

次の厄介な問題は、JavaScriptがすでに何かをするのに忙しい間に、ある間隔が起動した場合(前の間隔の処理など)です。この場合、間隔は記憶され、前のハンドラが終了してブラウザに制御が戻るとすぐに発生します。たとえば、doStuff()プロセスの場合は、短い([ - ])、時には長い([-----])場合があります。

.    *    *    •    *    •    *    *
     [-]  [-----][-][-----][-][-]  [-]

•コードをすぐに実行できず、代わりに保留にされたインターバルの起動を表します。

そのため、間隔を空けてスケジュールに戻るようにします。しかし、それらは互いの上に1つを並べることはしません:間隔ごとに保留中の実行が1つだけである場合もあります。 (もしそれらがすべて待ち行列に入っていたら、ブラウザは未処理の実行の増え続けるリストを残されるでしょう!)

.    *    •    •    x    •    •    x
     [------][------][------][------]

xは、実行できなかったり保留にされたりする可能性があるインターバル・ファイアリングを表すため、代わりに破棄されました。

DoStuff()関数の実行に通常設定されている間隔よりも長い時間がかかる場合、ブラウザはそれを処理するために100%CPUを消費し、応答が遅くなる可能性があります。

あなたはどちらを使いますか、そしてなぜですか?

Chained-Timeoutはブラウザに保証された空き時間を与えます。 Intervalは、ブラウザのUIの可用性を犠牲にして、実行中の機能がスケジュールされた時間にできるだけ近い時間で実行されるようにします。

1回限りのアニメーションの間隔はできるだけスムーズにしたいと考えていますが、連鎖タイムアウトは、ページが読み込まれている間中ずっと行われる継続的なアニメーションには丁寧です。それほど要求の厳しい用途(30秒ごとに起動する簡単なアップデータなど)では、どちらでも安全に使用できます。

ブラウザの互換性の観点から、setTimeoutはsetIntervalよりも前ですが、今日お会いするブラウザは両方をサポートしています。長年の最後の問題はWinMo <6.5ではIE Mobileでしたが、うまくいけばそれもまた私たちの背後にあります。

637
bobince

setInterval()

setInterval()は時間間隔に基づくコード実行方法で、間隔に達すると指定されたスクリプトを繰り返し実行することができます。それははデフォルトで[} _になるので、それをループさせるためにスクリプト作成者によってnotコールバック関数にネストされるべきです。あなたがclearInterval()を呼び出さない限り、それはその間隔で発火し続けるでしょう。

もしあなたがアニメーションや時計の目盛りでコードをループしたいのなら、setInterval()を使ってください。

function doStuff() {
    alert("run your code here when time interval is reached");
}
var myTimer = setInterval(doStuff, 5000);

setTimeout()

setTimeout()は、時間が経過したときにのみスクリプトを実行する時間ベースのコード実行方法です。{one time runする関数の内側にsetTimeout()オブジェクトを入れ子にしてスクリプトをループさせるのでなければ、これは再びnot繰り返されません。ループするように設定されている場合は、clearTimeout()を呼び出さない限り、その間隔で発火し続けます。

function doStuff() {
    alert("run your code here when time interval is reached");
}
var myTimer = setTimeout(doStuff, 5000);

指定した時間の経過後に何かが起こるようにしたい場合は、setTimeout()を使用してください。これは、指定した間隔に達すると1回だけ実行されるためです。

85
Haris

SetIntervalを使用すると、将来のコードの実行を簡単にキャンセルできます。 setTimeoutを使用する場合、後でキャンセルしたい場合に備えて、タイマーIDを追跡する必要があります。

var timerId = null;
function myTimeoutFunction()
{
    doStuff();
    timerId = setTimeout(myTimeoutFunction, 1000);
}

myTimeoutFunction();

// later on...
clearTimeout(timerId);

versus

function myTimeoutFunction()
{
    doStuff();
}

myTimeoutFunction();
var timerId = setInterval(myTimeoutFunction, 1000);

// later on...
clearInterval(timerId);
41
Kamiel Wanrooij

タイムアウトをキャンセルしたい場合はsetTimeoutメソッドが使いやすいと思います。

function myTimeoutFunction() {
   doStuff();
   if (stillrunning) {
      setTimeout(myTimeoutFunction, 1000);
   }
}

myTimeoutFunction();

また、関数内で問題が発生した場合でも、1秒ごとにエラーを繰り返すのではなく、最初のエラーで繰り返しを停止します。

21
Guffa

非常に違いはそれらの目的にあります。

setInterval()
   -> executes a function, over and over again, at specified time intervals  

setTimeout()
   -> executes a function, once, after waiting a specified number of milliseconds

それはそれと同じくらい簡単です

より複雑な詳細はこちら http://javascript.info/tutorial/settimeout-setinterval

16
kmario23

SetInterval内でいくつかの関数を実行すると、タイムアウトよりも長い時間動作します->ブラウザがスタックします。

-たとえば、doStuff()は1500秒かかります。実行するには、次のようにします:setInterval(doStuff、1000);
1)ブラウザの実行doStuff()これには1.5秒かかります。実行される;
2)〜1秒後、doStuff()を再度実行しようとします。ただし、前のdoStuff()は引き続き実行されます->ブラウザーはこの実行をキューに追加します(最初に実行した後に実行するため)。
3,4、..)次の繰り返しの実行キューへの追加は同じですが、前からのdoStuff()はまだです進行中...
その結果、ブラウザがスタックします。

この動作を防ぐための最良の方法は、setTimeout内でsetTimeoutを実行してsetIntervalをエミュレートすることです。
setTimeout呼び出し間のタイムアウトを修正するには、 JavaScriptのsetIntervalの自己修正の代替 テクニックを使用できます。

12

私はsetTimeoutを使います。

明らかに違いはsetTimeoutはメソッドを1回呼び出し、setIntervalはそれを繰り返し呼び出すことです。

これが違いを説明する良い記事です: チュートリアル:setTimeoutとsetIntervalを使ったJavaScriptタイマー

7
Bravax

私はsetInterval(func, milisec)の簡単なテストをしました、なぜなら私は関数の時間消費がインターバル期間より大きいとき何が起こるか知りたかったからです。

setIntervalは、 一般に 直前の反復の start の直後に次の反復をスケジュールします。 関数がまだ進行中でない限り 。もしそうなら、setIntervalは関数が終了するまで待ちます。それが起こるとすぐに、関数はすぐに再び起動されます - スケジュールに従って次の反復を待つことはありません(それは時間超過関数のない条件の下であるように)。並列反復が実行されている状況もありません。

私はこれをChrome v23でテストした。私はそれがすべての最近のブラウザにわたる決定論的な実装であることを願っています。

window.setInterval(function(start) {
    console.log('fired: ' + (new Date().getTime() - start));
    wait();
  }, 1000, new Date().getTime());

コンソール出力:

fired: 1000    + ~2500 ajax call -.
fired: 3522    <------------------'
fired: 6032
fired: 8540
fired: 11048

wait関数は単なるスレッドブロッキングヘルパー - 同期ajax呼び出しで、サーバー側では 2500ミリ秒 の処理が必要です。

function wait() {
    $.ajax({
        url: "...",
        async: false
    });
}
5
jwaliszko

あなたのコードは異なる実行意図を持っているでしょう、そしてオンラインゲームのようないくつかのプロジェクトではそれは受け入れられません。まず、コードを同じ間隔で機能させるには、「myTimeoutFunction」を次のように変更する必要があります。

function myTimeoutFunction()
{
    setTimeout(myTimeoutFunction, 1000);
    doStuff();
}
myTimeoutFunction()

この変更の後、それはになります

function myTimeoutFunction()
{
    doStuff();
}
myTimeoutFunction();
setInterval(myTimeoutFunction, 1000);

しかし、JSはシングルスレッドなので、まだ安定した結果は得られません。今のところ、もしJSスレッドが何かで忙しいなら、それはあなたのコールバック関数を実行することができないでしょう、そして実行は2-3ミリ秒の間延期されるでしょう。毎秒60回の実行があり、ランダムな1〜3秒の遅延があるたびに、それは絶対に許容できないでしょう(1分後には7200ミリ秒の遅延になるでしょう)。

    function Timer(clb, timeout) {
        this.clb = clb;
        this.timeout = timeout;
        this.stopTimeout = null;
        this.precision = -1;
    }

    Timer.prototype.start = function() {
        var me = this;
        var now = new Date();
        if(me.precision === -1) {
            me.precision = now.getTime();
        }
        me.stopTimeout = setTimeout(function(){
            me.start()
        }, me.precision - now.getTime() + me.timeout);
        me.precision += me.timeout;
        me.clb();
    };

    Timer.prototype.stop = function() {
        clearTimeout(this.stopTimeout);
        this.precision = -1;
    };

    function myTimeoutFunction()
    {
        doStuff();
    }

    var timer = new Timer(myTimeoutFunction, 1000);
    timer.start();

このコードは安定した実行期間を保証します。たとえスレッドがビジー状態になり、あなたのコードが1005ミリ秒後に実行され、次回は995ミリ秒の間タイムアウトになり、結果は安定するでしょう。

3
degr

少し違った見方をすると、setIntervalは、コードが実行されるまでの待機時間をsetTimeoutで設定しながら、指定した間隔(1000ms、または指定した量)ごとにコードが実行されるようにします。コードの実行には数ミリ秒かかるため、最大1000ミリ秒かかるので、setTimeoutは不正確な時間(1000ミリ秒を超える時間)にまた実行されます。

たとえば、タイマー/カウントダウンはsetTimeoutでは実行されず、setIntervalで実行されます。遅延は発生せず、コードは指定された間隔で実行されます。

3
CatalinBerta

SetIntervalとsetTimeoutはどちらも、実行をキャンセルするために、つまりタイムアウトが発生する前に使用できるタイマーIDを返します。キャンセルするには、次のようにclearIntervalまたはclearTimeoutを呼び出します。

var timeoutId = setTimeout(someFunction, 1000);
clearTimeout(timeoutId);
var intervalId = setInterval(someFunction, 1000),
clearInterval(intervalId);

また、ページを離れるかブラウザウィンドウを閉じると、タイムアウトは自動的にキャンセルされます。

3
Helgi

まあ、setTimeoutはある状況では私が今学んだように優れています。私はいつもsetIntervalを使います。これは私が30分以上バックグラウンドで走らせるために残しました。私がそのタブに戻ったとき、スライドショー(コードが使用されていた)は、5秒ごとではなく、非常に急激に変化していました。 setTimeoutではそのような状況は完全に不可能なので、私がそれをさらにテストし、それがブラウザのせいであるかどうかは重要ではないかどうかは、実際には再び起こります。

2
Nino

次のJavaScriptを実行するか、または JSFiddle をチェックすると、自分でbobinceの回答を検証できます。

<div id="timeout"></div>
<div id="interval"></div>

var timeout = 0;
var interval = 0;

function doTimeout(){
    $('#timeout').html(timeout);
    timeout++;
    setTimeout(doTimeout, 1);
}

function doInterval(){
    $('#interval').html(interval);
    interval++;
}

$(function(){
    doTimeout();
    doInterval();
    setInterval(doInterval, 1);
});
2
Gudradain

すでに述べたことを追加するだけで、setTimeoutバージョンのコードもMaximum call stack sizeに到達し、機能しなくなります。再帰関数が止まる基本的なケースはないので、 永遠に実行させることはできません。

1
Maaz

違いはコンソールで明白です:

enter image description here

1
testCoder