setTimeoutまたはsetInterval?


763

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

オプションA:

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

myTimeoutFunction();

オプションB:

function myTimeoutFunction()
{
    doStuff();
}

myTimeoutFunction();
setInterval(myTimeoutFunction, 1000);

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


6
JSのタイマーがどのように機能するかについての詳細が必要な場合は、John Resigがこのトピックに関する優れた記事を書いた
Rafael

9
setTimeoutは、伝播を維持するために追加のコード行を必要とする明らかな違いもあります。これには、メンテナンスの問題であるという欠点がありますが、期間を簡単に変更できるという利点があります
annakata

これを試してくださいjsfiddle.net/pramendra/Y4vEV
Pramendra Gupta

4
@JapanProに感謝しますが、タイムアウトが機能するのに本当に問題はありませんでした。この投稿は、違いが何で、どちらを使用すべきかについての記事でした。
Damovisa、2011年

回答:


670

彼らは基本的に同じことをしようが、setIntervalアプローチがより正確になるsetTimeoutため、アプローチsetTimeoutを待機さ1000ミリ秒、関数を実行し、別のタイムアウトを設定します。そのため、待機期間は実際には1000msより少し長くなります(または、関数の実行に長い時間がかかる場合はさらに長くなります)。

それは正確に1000msごとにsetInterval実行されると考えるかもしれませんが、JavaScriptはマルチスレッド言語ではないため、遅延も発生することに注意することが重要です。つまり、スクリプトの他の部分が実行されている場合、間隔はそれが完了するのを待つ。setInterval

、このフィドル間隔は(スクリプトがやろうとしている)は、第2のほぼ1コール/で、ほぼすべての時間でありながら、あなたは明らかに、タイムアウトが背後に落ちることがわかります。上部の速度変数を20のような小さな値に変更すると(つまり、毎秒50回実行しようとすることを意味します)、間隔が平均で毎秒50回の反復に達することはありません。

遅延はほとんど常に無視できますが、本当に正確なものをプログラミングしている場合は、自動調整タイマーを使用する必要があります(これは本質的に、作成された遅延に合わせて常に調整するタイムアウトベースのタイマーです)。


4
アンディも同様の提案をしました。仮に、これは、メソッドの実行に1000ミリ秒以上かかる場合、同時に複数を実行できることを意味しますか?
Damovisa 2009

14
理論的にはそうです。実際には、JavaScriptはマルチスレッドをサポートしていないため、できません。コードに1000ミリ秒以上かかる場合、ブラウザがフリーズします。
カミエルワンルーイ2009

61
技術的には、タイマーの精度と他のコードがすでに実行されているかどうかに依存するため、コードは正確に1000msごとに実行されるわけではありません。あなたの主張はまだ残っています。
Matthew Crumley、

10
setIntervalは2つの点で異なります。1。setIntervalは再帰的ではなく、setIntervalは指定された時間の後で初めて関数を呼び出しますが、setTimeoutは遅延なしで最初に呼び出され、その後、指定された時間の後に再び呼び出されます。最初の実行後、それらはほとんど同じように動作します。
Hafiz、2011

5
違いは、setTimeoutが繰り返されないことです。設定された時間後にスクリプトを実行できますが、1回だけです。一方、setIntervalは、clearTimeout()で停止されるまで、そのスクリプトを繰り返します。
Leander

648

違いはありますか?

はい。Timeoutは、setTimeout()が呼び出されてから一定時間実行されます。間隔は、前の間隔が発生した後、一定時間実行されます。

doStuff()関数の実行に時間がかかる場合は、違いがわかります。たとえば、setTimeout / setIntervalへの呼び出しを.で、タイムアウト/インターバルの起動をで、*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でしたが、うまくいけば、それも今私たちの後ろにあります。


しかし、IntervalとTimeoutの間の選択の理由は、たとえばWebOSやJILなどの非ブラウザープラットフォームでも当てはまりますか?
Vid L

2
匿名関数でチェーンタイムアウトを実行するための良い方法:setTimeout(function(){setTimeout(arguments.callee、10)}、10)
Justin Meyer

1
ブラウザーの互換性に関しては、すべてのブラウザーが両方の方法を提供しますが、パフォーマンスは異なります。
unigg

「しかし、可能性としては、使用している他のものをサポートしていない可能性があります」非常に当てはまる
基本的な

1
setTimeout( "schedule()"、0);を使用したchromiumプロジェクトのドラムマシン。そのため、Chromeのバックグラウンドタブやリソースの不足時に、ブラウザに不要なスタックが発生することはありません。
エリオット・ヤップ、

91

setInterval()

setInterval()時間間隔ベースのコード実行メソッドで、間隔に達したときに指定されたスクリプトを繰り返し実行するネイティブ機能があります。デフォルトではループするため、ループを作成するためにスクリプト作成者がコールバック関数にネストすることはできません。を呼び出さない限り、その間隔で発砲し続けます。clearInterval()

アニメーションや時計の目盛りでコードをループする場合は、を使用しますsetInterval()

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

setTimeout()

setTimeout()間隔に達したときにスクリプトを1回だけ実行する時間ベースのコード実行メソッドです。実行するために呼び出す関数内にオブジェクトをネストしてスクリプトをループするようにギアを設定しない限り、再度繰り返されることはありませんsetTimeout()。ループするように設定されている場合、を呼び出さない限り、間隔で発砲し続けますclearTimeout()

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

指定した期間の後に1回だけ何かを実行したい場合は、を使用しますsetTimeout()。これは、指定された間隔に達したときに1回だけ実行されるためです。


6
すばらしい説明ですが、OPはOPが提供する例の基本的な違いを理解していることに注意してください。特に、OPのsetTimeout()例でsetTimeout()は、は再帰的に呼び出されますが、呼び出されsetInterval()ないことに注意してください。
DavidRR

44

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

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

myTimeoutFunction();

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

function myTimeoutFunction()
{
    doStuff();
}

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

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

35
setIntervalの場合、タイマーIDを追跡していないようです。機能から引き出されただけです。
Kekoa 2010年

1
もう1つのオプションsetTimeoutは、IDを保存するのではなく、if条件がtrueの場合にのみ次のタイムアウトを設定するステートメントを追加することです。
nnnnnn

7
ケコア、良い点。ただし、間隔IDを保存する必要があるのは1回だけです。タイムアウトIDは呼び出しのたびに変わる可能性があるため、これらの変更を追跡する必要があります。タイムアウトをクリアしたいコードは、どういうわけかこの変数の現在の値にアクセスできなければなりません。さらにdoStuff、IDが無効であるため、実行中にタイムアウトをクリアすることはできません。ただし、タイムアウトIDを保存する必要はありません。代わりに、呼び出しを停止できますsetTimeout
ロバート

4
私の経験では、ほとんどの場合、setTimeoutを使用しているときでもキャンセルできるようにしたいと思っています。次の呼び出しが終了した後ではなく、次の呼び出しが発生するにキャンセルする時間の99%。
Kamiel Wanrooij

23

setTimeoutタイムアウトをキャンセルしたい場合は、この方法が使いやすいと思います。

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

myTimeoutFunction();

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


20

非常に異なるのは、その目的です。

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


7
簡潔に説明しますが、OPはOPが提供する例の基本的な違いを理解していることに注意してください。特に、OPのsetTimeout()例でsetTimeout()は、は再帰的に呼び出されますが、呼び出されsetInterval()ないことに注意してください。
DavidRR

14

setInterval内で何らかの関数を実行すると、timeoutよりも長く機能します->ブラウザーがスタックします。

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

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


1
なぜ誰もこの答えに価値を見つけられなかったのかわかりません!
Randika Vishman、2015年

9

私はsetTimeoutを使用しています。

どうやら違いは、setTimeoutがメソッドを1回呼び出し、setIntervalが繰り返し呼び出すことです。

違いを説明する優れた記事を次に示します。チュートリアル:setTimeoutとsetIntervalを使用したJavaScriptタイマー


2
うん、私はその違いを得たが、私が提供したコードの2枚が同じことを行う必要があります...
Damovisa

うーんはい...私は考えていたでしょう...しかし、dcauntと彼の投票数によると、それは実際に起こることではありません。
Bravax 2009

9

コードの実行間隔は異なり、オンラインゲームなどの一部のプロジェクトでは受け入れられません。最初に、何をすべきか、同じ整数でコードを機能させるには、「myTimeoutFunction」を次のように変更する必要があります。

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

この変更後、次と等しくなります。

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

ただし、JSはシングルスレッドであるため、安定した結果は得られません。現時点では、JSスレッドが何かでビジー状態になると、コールバック関数を実行できなくなり、実行は2〜3ミリ秒延期されます。1秒あたり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ミリ秒のタイムアウトがあり、結果は安定しています。


7

setInterval(func, milisec)関数の時間の消費が間隔の継続時間よりも大きい場合に何が起こるか知りたくて、私はの簡単なテストを行いました。

setInterval、一般的に直後に次の反復をスケジュール開始、前の反復の機能がまだ進行中である場合を除き。その場合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関数は単なるスレッドブロックヘルパーであり、サーバー側での処理にちょうど2500ミリ秒かかる同期ajax呼び出しです。

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

1
「並列反復が実行されている状況はありません」-はい、これは不可能であるべきです。クライアント側のJavaScriptにはシングルスレッドの実行モデルがあるため、何も(イベントハンドラーなど)同時に発生することはありません。これが、同期ajax呼び出し中に何も起こらない(そしてブラウザーが応答しない)理由です。
MrWhite 2012年

「間隔」の間の数ミリ秒でブラウザは応答しますか?保留中の場合、別のイベントが発生しますか?(btw +1テストありがとうございます)
MrWhite 2012年

1
MDNによれば、関数がインターバル時間よりも長く実行できる場合、「危険な使用法」と見なされます。再帰setTimout呼び出しが推奨されます。
MrWhite

6

少し違った見方をすると:setIntervalは、コードが指定された間隔(つまり、1000ミリ秒、または指定した時間)で実行されることを保証し、setTimeoutはコードが実行されるまで待機する時間を設定します。また、コードの実行に追加のミリ秒がかかるため、合計で1000ミリ秒になるため、setTimeoutは不正確な時間(1000ミリ秒超)で再度実行されます。

たとえば、タイマー/カウントダウンはsetTimeoutでは行われず、setIntervalで行われます。これにより、タイマーが遅延せず、コードが所定の間隔で実行されます。


5

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

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

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


4

次のjavascriptを実行するか、このJSFiddleを確認すると、自分でボビンスの回答を検証できます

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

3

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


呼び出している関数内でsetIntervalを呼び出したかのように聞こえます。これがsetTimeoutでループする方法ですが、setIntervalでは、呼び出されるたびにまったく新しいループが実際に作成されます。
スティーブンR


2

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


これは本当だとは思いません。こちらをご覧くださいstackoverflow.com/questions/8058612/…–
ケビンウィーラー、

-1

とsetInterval(expression、duration)の最も一般的な違いは、

setTimeout()は、ONCEのみの式を実行し、その指定された期間の後にそれを実行します。

しかしながら、

setInterval()は、指定された各期間の後にINFINITE-LOOPで式を実行します。


-5

私が考えるSetIntervalSetTimeout異なっています。SetInterval設定された時間に従ってSetTimeoutブロックを実行し、コードのブロックを1回実行します。

タイムアウトカウントダウン秒後にこれらのコードセットを試してください。

setInterval(function(e){
    alert('Ugbana Kelvin');
}, 2000);

してみてください

setTimeout(function(e){
    alert('Ugbana Kelvin');
}, 2000);

違いがわかります。


これは質問の答えにはなりません。settimeout()を再帰的に使用して、setintervalと同じ結果を得ることができます。問題は、これら2つのオプションのパフォーマンスに関するものでした。
Tomas Gonzalez、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.