setInterval の挙動を学習しました

2011/12/03

CloudCloudCloudってのを作ってまして。 Facebook上で zonoise さんにいろいろ教えてもらってて。 で指摘受けたところをなおそうとしてたらハマったわけです、setIntervalの挙動に。

<script type="text/javascript">
var interval = 1000
for( var num = 0 ; num < 12 ; num ++ ){
    alert("1:" + num);      // 1
    setInterval(function(){
        alert("2:" + num);  // 2
    },interval);
    alert("3:" + num);      // 3
}
</script>

でbashでいうところの

interval=1
fuction setInterval()
{
  sleep $1
}
for num in `seq 0 11`
do
  echo "1:${num}"
  echo "2:${num}"
  setInterval ${interval}
  echo "3:${num}"
done

みたいなのを想像してた。 1 → 2 → setInterval(つまりsleep) → 3 → 1 → 2 → setInterval(つまりsleep) → 3 … と実行されるだろう、という期待をしてたので、 1 → 3 → setInterval(つまりsleep) → 1 → 3 → setInterval(つまりsleep) → 1 → 3 → setInterval(つまりsleep) … → 2 → 2 → 2 → … みたいな挙動に面食らったわけです。 で、Twitter上でotherworldyさんにもアドバイス受けたりしてようやく理解したわけですねー。

for(i=0;i<10;i++){
  setInterval(function(){ action(i);  },INTERVAL);}
}
action2;

ってのは、 INTERVALが過ぎないとsetIntervalで括ったfunction(){ action(i) }は、 全く実行されないんですね。 でその外側においておいた for の i++ がどんどん実行されるがために、 action の引数として利用しようと考えていたfor文由来の変数iが、 forの想定した最大値まで達しちゃうわけですねー。

「じゃあお前は結局どうしたのか?」っていうと for文を使うのをやめました。 そもそもsetIntervalがループの役目果たしてたので、

var i=0
setInterval(function(){
  action(i);
    if( i >= 10 ){ action2;}
    i++;
  },INTERVAL);}
}

としました。すげーすっきりした。 ※ちなみに action2 には “window.location.reload();” を想定していた。