[JavaScript] setIntervalで0秒発火ロジックを用いる際のclearInterval制御

JavaScriptでタイマー処理を実現する際によく利用する「setInterval」。

指定した間隔(ミリ秒)で第1引数の処理が実行されるのだが、最初に処理実行される前にも待機時間が生じるためすぐに実行したい場合は即時関数を用いれば良い。

var timerID = setInterval((function () {
  /* 処理 */

  return arguments.callee;
}()), 500);

これは各所で紹介されているスマートなロジックですが、この処理の中に「clearInterval」を組み入れる場合は注意が必要。


初回実行時はtimerIDがまだセットされていない状態なので素直にclearIntervalを呼んでもタイマー解除出来ません。そこで、初回実行時に終了条件を満たした場合に限りclearIntervalするだけの処理に置き換えてしまえばOK。

var timerID = setInterval((function () {
  /* 処理 */

  if (/* 終了条件を満たした時 */) {
    if (!timerID) {
      /* 初回実行時 */
      return function () {
        clearInterval(timerID);
      };
    } else {
      /* 2回目以降実行時 */
      clearInterval(timerID);
    }
  }
  return arguments.callee;
}()), 500);

以外にハマっている人が多いようなのでお気をつけください。

strictモード対応(2018-02-07)

ECMAScript 第5版ではstrictモードにおける「arguments.callee()」の使用が禁止されていますが、関数式に名前を付ければ対処可能です。

また、初回で終了条件を満たした際は単純にreturnしておくことで2回目以降の実行を抑制することが出来ます。

var timerID = setInterval((function _f() {
  /* 処理 */

  if (/* 終了条件を満たした時 */) {
    /* 初回実行時 */
    if (!timerID) return;

    /* 2回目以降実行時 */
    clearInterval(timerID);
  }
  return _f;
}()), 500);

なお、上記の変数timerIDをvarではなくletで定義したい場合は、先に宣言しておくこと。でないと「Uncaught ReferenceError: timerID is not defined」で怒られます。


/* 先に変数宣言 */
let timerID;
timerID = setInterval((function _f() {
  /* 処理 */

  if (/* 終了条件を満たした時 */) {
    /* 初回実行時 */
    if (!timerID) return;

    /* 2回目以降実行時 */
    clearInterval(timerID);
  }
  return _f;
}()), 500);

    This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

    頂戴したコメントは管理者に承認されるまで表示されません。また、メールアドレスが公開されることはありません。
    このサイトはreCAPTCHAによって保護されており、Googleのプライバシーポリシー利用規約が適用されます。