793

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

オプション A:

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

myTimeoutFunction();

オプション B:

function myTimeoutFunction()
{
    doStuff();
}

myTimeoutFunction();
setInterval(myTimeoutFunction, 1000);

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

4

20 に答える 20

692

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

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

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

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

于 2009-04-08T13:14:46.583 に答える
659

違いはありますか?

はい。Timeout は、setTimeout() が呼び出された後、一定時間実行されます。Interval は、前の間隔が起動された後、一定の時間実行されます。

doStuff() 関数の実行に時間がかかる場合、違いに気付くでしょう。たとえば、setTimeout/setInterval の呼び出しを で表し、.タイムアウト/間隔の起動を で表し、 *JavaScript コードの実行をで表すと[-----]、タイムラインは次のようになります。

Timeout:

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

Interval:

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

次の複雑な点は、JavaScript が何か (前の間隔の処理など) で既にビジー状態である間に間隔が発生した場合です。この場合、間隔が記憶され、前のハンドラーが終了してブラウザーに制御が戻るとすぐに発生します。たとえば、短い ([-]) ときも長い ([-----]) ときもある doStuff() プロセスの場合:

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

• は、そのコードをすぐに実行できず、代わりに保留になった間隔発火を表します。

そのため、間隔はスケジュールに戻るために「追いつく」ようにします。ただし、それらは互いに重ねてキューに入れません。間隔ごとに保留中の実行は 1 つだけです。(それらがすべてキューに入れられた場合、ブラウザーには未処理の実行の拡大し続けるリストが残されます!)

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

x は、実行または保留にできなかったため、代わりに破棄された間隔発火を表します。

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

どちらを使用し、その理由は何ですか?

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

可能な限りスムーズにしたい 1 回限りのアニメーションの間隔を検討しますが、ページが読み込まれている間に常に発生する進行中のアニメーションには、連鎖したタイムアウトの方が丁寧です。要求の少ない用途 (30 秒ごとに起動する単純なアップデーターなど) では、どちらも安全に使用できます。

ブラウザーの互換性に関しては、setTimeout は setInterval より前から存在しますが、現在遭遇するすべてのブラウザーは両方をサポートしています。長年の最後のストラグラーは、WinMo 6.5 未満の IE Mobile でしたが、それも今や私たちの背後にあることを願っています。

于 2009-04-08T20:13:28.137 に答える
95

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 回だけ実行されるためです。

于 2013-08-14T05:12:32.157 に答える
45

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);
于 2009-04-08T13:25:24.420 に答える
23

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

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

myTimeoutFunction();

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

于 2009-04-08T14:20:02.760 に答える
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

于 2014-01-11T10:16:45.857 に答える
16

setInterval 内で何らかの関数を実行すると、タイムアウトよりも多くの時間がかかります-> ブラウザが動かなくなります。

- たとえば、doStuff()には 1500 秒かかります。setInterval(doStuff, 1000); を実行します。
1) ブラウザでdoStuff()を実行すると、1.5 秒かかります。実行されます。
2) 約 1 秒後にdoStuff()を再度実行しようとします。しかし、以前のdoStuff()はまだ実行されているため、ブラウザーはこの実行をキューに追加します (最初の実行後に実行するため)。
3,4,..) 次の繰り返しの実行キューに同じように追加されますが、以前のdoStuff()はまだ進行中です...
結果として、ブラウザーが動かなくなります。

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

于 2014-04-26T17:42:53.623 に答える
10

コードにはさまざまな実行間隔があり、オンライン ゲームなどの一部のプロジェクトでは受け入れられません。まず、コードを同じ間隔で機能させるには、「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 ミリ秒のタイムアウトが発生し、結果は安定します。

于 2016-12-24T11:32:08.653 に答える
9

私は setTimeout を使用します。

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

違いを説明する良い記事は次のとおりです:チュートリアル: setTimeout と setInterval を使用した JavaScript タイマー

于 2009-04-08T13:15:52.290 に答える
7

setInterval(func, milisec)関数の時間の消費が間隔の期間よりも大きい場合に何が起こるのか興味があったので、の簡単なテストを行いました。

setInterval関数がまだ進行中でない限り、通常、前の反復の開始直後に次の反復をスケジュールします。その場合、関数が終了するまで待機します。それが発生するとすぐに、関数はすぐに再起動されます-スケジュールに従って次の反復を待つ必要はありません(関数を超える時間がない条件下であるため)。並列反復が実行されている状況もありません。setInterval

Chromev23でこれをテストしました。私はそれがすべての現代のブラウザにわたる決定論的な実装であることを望みます。

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
    });
}
于 2012-11-25T22:20:23.383 に答える
6

少し別の見方をすると、setInterval は指定された間隔 (つまり、1000 ミリ秒または指定した時間) ごとにコードが実行されるようにし、setTimeout はコードを実行するまで待機する時間を設定します。コードの実行には余分なミリ秒がかかるため、合計すると 1000 ミリ秒になり、setTimeout は不正確な時間 (1000 ミリ秒以上) に再度実行されます。

たとえば、タイマー/カウントダウンは setTimeout では行われず、setInterval で行われ、遅延がなく、コードが正確に指定された間隔で実行されるようにします。

于 2015-01-27T20:25:28.987 に答える
6

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

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

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

于 2009-04-08T14:47:06.423 に答える
3

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

于 2011-10-18T16:48:42.097 に答える
2

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

于 2014-05-26T15:43:34.317 に答える