{javascript} clearIntervalの使い方

clearIntervalしても止まらないんだけど!?な時

勘のいい人用に一言で終わらせると、「setInterval自体は一度しか実行されない」



では、以下勘の悪い人用

まず間違った書き方

//実行される度に1ずつ増やして出力
var i = 0;
function hoge(){
  console.log(i++);
}

//1000ms毎にhoge()を実行
var tid = setInterval(function(){
  hoge();
}, 1000);

//3秒を超えたら停止?
if (i > 3){
  clearInterval(tid);
  console.log("停止");
}

まず理解しないといけないのは、setIntervalは一度しか行われていないということ。
setIntervalで一定時間毎にhoge()を行うとは記述してあるが、setInterval自体を何度も行っているわけではない。
あくまで流れとしては

-処理開始-
①setIntervalを実行(hogeが1000msごとに実行されることが予約される)
②i>3を評価
-処理終了-

だから、①と②がまず一瞬で処理される。
当然この場合、if文に差し掛かる段階ではsetIntervalは実行されてるけどhoge()が3回も実行されるほど時間がたってない。
よってif文ではfalseが返され、clearIntervalは実行されない
その後もsetIntervalは実行されないが、命令自体は生きているので1000ms毎にhoge()は実行され続ける。

なのでこう書くことになる

//実行される度に1ずつ増やして出力
var i = 0;
function hoge(){
  console.log(i++);
}

//1000ms毎にhoge()とif文を実行
var tid = setInterval(function(){
  hoge();
  if(i > 3){
    clearInterval(tid);
  }
}, 1000);

一応流れを書くと、

-処理開始-
①setIntervalを実行
-処理終了-

となるわけだから、setIntervalが一回実行されて処理終了。
ただ命令自体は生きているので、1000ms毎にhoge()とif文が実行され続ける。
この書き方ならhoge()が実行され続ける限り、同時にif文も実行されるので、i>3がtrueになった時clearIntervalが実行、相手(setInterval)は死ぬ。


ちなみにifを先に持ってきてしまうと、この場合コンソールには4まで表示されるので気をつけよう。
これも勘のいい人用に一言で終わらせると、「clearIntervalはbreakじゃない」

var tid = setInterval(function(){
  if(i > 3){
    clearInterval(tid);
  }
  hoge();
}, 1000);

この時の処理

setInterval開始

if実行 //0 > 3 -> false
hoge()実行 //0表示

if実行 //1 > 3 -> false
hoge()実行 //1表示

〜中略〜

if実行 //4 > 3 -> true (次回からsetIntervalの中身は実行されない)
hoge()実行 //4表示 (3回目にclearIntervalされなかった段階で、4回目のhoge()が約束される)

いくらclearIntervalしたとしても、すでに始まってる処理をその瞬間抜けるわけじゃないことに注意。
forやwhileなどでは、breakが記述されてる部分からループ外に飛ぶわけだけど、clearIntervalはbreakとは全然別物だということ。

歯医者さん行きたくない