web-dev-qa-db-ja.com

初めて遅れることなくsetInterval関数を実行する

メソッドをすぐに実行してからタイマーで実行するようにjavascriptのsetIntervalメソッドを設定する方法があります

275
Jorge

初めて関数を直接自分で呼び出すのが最も簡単です。

foo();
setInterval(foo, delay);

ただし、setIntervalを回避するのには十分な理由があります。特に、状況によっては、setIntervalイベントがすべて遅滞なくすぐに到着することがあります。もう1つの理由は、ループを停止したい場合はclearIntervalを明示的に呼び出す必要があるため、元のsetInterval呼び出しから返されたハンドルを覚えておく必要があるということです。

そのため、代わりの方法は、代わりにfooを使用して後続の呼び出しのためにsetTimeoutを自分自身でトリガーすることです。

function foo() {
   // do stuff
   // ...

   // and schedule a repeat
   setTimeout(foo, delay);
}

// start the cycle
foo();

これは、呼び出しの間に少なくともdelayの間隔があることを保証します。また、必要に応じてループをキャンセルするのも簡単になります。ループの終了条件に達したときにsetTimeoutを呼び出さないでください。

さらに良いことに、それをすべてすぐに呼び出される関数式で囲むことができます。ループ:

(function foo() {
    ...
    setTimeout(foo, delay);
})();

これは機能を定義し、一度にすべてのサイクルを開始します。

441
Alnitak

私があなたを正しく理解しているかどうかはわかりませんが、次のようなことを簡単に行うことができます。

setInterval(function hello() {
  console.log('world');
  return hello;
}(), 5000);

これを行うには明らかにいくつもの方法がありますが、それが私が考えることができる最も簡潔な方法です。

178
chjj

私は同じ問題のためにこの質問に出くわしましたがsetInterval()のように正確に振る舞う必要な場合には答えはどれも役に立ちませんが、only違いはすぐに呼び出されるということです。始まりです。

これがこの問題に対する私の解決策です:

function setIntervalImmediately(func, interval) {
  func();
  return setInterval(func, interval);
}

このソリューションの利点:

  • setIntervalを使用している既存のコードは、置換によって容易に適応させることができます
  • 厳密モードで動作します
  • 既存の名前付き関数とクロージャで動作します。
  • 戻り値を使用して後でclearInterval()に渡すことができます

例:

// create 1 second interval with immediate execution
var myInterval = setIntervalImmediately( _ => {
        console.log('hello');
    }, 1000);

// clear interval after 4.5 seconds
setTimeout( _ => {
        clearInterval(myInterval);
    }, 4500);

生意気なことに、もしあなたが本当にsetIntervalを使う必要があるなら、元のsetIntervalを置き換えることもできます。したがって、既存のコードの前にこれを追加するときにコードを変更する必要はありません。

var setIntervalOrig = setInterval;

setInterval = function(func, interval) {
    func();
    return setIntervalOrig(func, interval);
}

それでも、上記のすべての利点がここでも適用されますが、代替は必要ありません。

10
Jens Wirth

その振る舞いを提供する関数でsetInterval()をラップすることができます。

function instantGratification( fn, delay ) {
    fn();
    setInterval( fn, delay );
}

...そしてそれを次のように使います。

instantGratification( function() {
    console.log( 'invoked' );
}, 3000);
6
user113716

あなたがそれを必要とするならば、これをきれいにするためのラッパーはここにあります:

(function() {
    var originalSetInterval = window.setInterval;

    window.setInterval = function(fn, delay, runImmediately) {
        if(runImmediately) fn();
        return originalSetInterval(fn, delay);
    };
})();

SetIntervalの3番目の引数をtrueに設定すると、setIntervalを呼び出した直後に初めて実行されます。

setInterval(function() { console.log("hello world"); }, 5000, true);

または3番目の引数を省略しても、元の動作は維持されます。

setInterval(function() { console.log("hello world"); }, 5000);

一部のブラウザでは、このラッパーで考慮されていないsetIntervalに対して 追加の引数 がサポートされています。これらはめったに使われないと思いますが、必要ならば覚えておいてください。

6
Mahn

誰かにとってそれはまるでそれが矢印関数であるかのように内側の外側のthisを持ってくる必要があります。

(function f() {
    this.emit("...");
    setTimeout(f.bind(this), 1000);
}).bind(this)();

上記のゴミが気になる場合は、代わりにクロージャを作成できます。

(that => {
    (function f() {
        that.emit("...");
        setTimeout(f, 1000);
    })();
})(this);

あるいは、コードによっては @autobindデコレータ を使うことを検討してください。

// YCombinator
function anonymous(fnc) {
  return function() {
    fnc.apply(fnc, arguments);
    return fnc;
  }
}

// Invoking the first time:
setInterval(anonymous(function() {
  console.log("bar");
})(), 4000);

// Not invoking the first time:
setInterval(anonymous(function() {
  console.log("foo");
}), 4000);
// Or simple:
setInterval(function() {
  console.log("baz");
}, 4000);
1
NSD

次の順序で関数を呼び出すことをお勧めします

var _timer = setInterval(foo, delay, params);
foo(params)

特定の条件でclearInterval(_timer)を使いたい場合、_timerをfooに渡すこともできます。

var _timer = setInterval(function() { foo(_timer, params) }, delay);
foo(_timer, params);
1
Jayant Varshney

firstInterval という便利なnpmパッケージがあります(完全な開示、私のものです)。

ここに挙げた例の多くはパラメータ処理を含んでいません、そしてどんな大規模プロジェクトでもsetIntervalのデフォルトの振る舞いを変えることは悪です。ドキュメントから:

このパターン

setInterval(callback, 1000, p1, p2);
callback(p1, p2);

と同じです

firstInterval(callback, 1000, p1, p2);

あなたがブラウザの古い学校で依存関係を望まないのなら、それは コードからの簡単なカットアンドペーストです。

0
jimm101

これは初心者向けの簡単なバージョンです。それは単に関数を宣言し、それを呼び出してから間隔を開始します。それでおしまい。

//Declare your function here
function My_Function(){
  console.log("foo");
}    

//Call the function first
My_Function();

//Set the interval
var interval = window.setInterval( My_Function, 500 );
0
Polyducks

この問題を解決するために、ページが読み込まれた後に初めて関数を実行します。

function foo(){ ... }

window.onload = function() {
   foo();
};

window.setInterval(function()
{
    foo(); 
}, 5000);
0
user4989618