javascript でのタイマー処理について (setInterval,setTimeout)
同じく前回の記事で書いたゲーム作成中の事です。
ゲーム内部の処理で、一定時間毎に問題の切り替え、正誤判定等を行いたいと考えていたところ、候補として二つの関数を発見しました。
setInterval と setTimeout です。
使ったり調べたりしている内に細かい挙動の違いが気になったのでメモとして。
両者とも基本的にループ処理に用いられる事が多い点などでは同じです。
簡単な相違点を見てみましょう。
setInterval の場合
大きな特徴としては、スタックやランタイムを考慮せずに指定時間毎に処理を行うという点です。
つまり、以下の画像内のコメントのような状態が起こり得る事になります。
この処理、実はsetTimeoutで書き換える事によって、ブラウザのクラッシュという問題を防ぐことが出来ます。
見てみましょう。
setTimeout の場合
setInterval と比較した場合の大きな特徴として、setTimeoutではスタックやランタイムを考慮するという特徴があります。
上記ソースコードのような「ある処理を三秒ごとに繰り返し」たい場合、こうなります。
最後の関数呼び出しでファンクションに入り、再帰的な処理が実行されるイメージです。
setInterval との違いは、一言で言うと前処理の終了を待つかどうかです。
このような記述により、予想しない結果が返されるのを防ぐことができます。
ループの停止
二つのコードを見て気づくと思いますが、上の処理は両方とも永久ループです。止まりません。
ということで、続いて二つの処理を止める方法を考えます。
まずはsetIntervalを用いたループの場合。
通常、カウンタぽいものを用いて止める形になります。
先述のコードを書き換えたものがこちらです。
カウンタ(1行目)をループ内でインクリメントさせ、3回目でループから抜け出しています。
コンソールも無事に。
ちなみに、カウンタの宣言をファンクション内に書いてしまうと、当然永久ループになります(呼び出しの度に生成されるので)。
次に、setTimeoutの場合。
停止処理追加後はこのようになります。
setIntervalでも同じような記述でしたが、setTimeoutそのものを変数に入れ、clearTimeout側の引数にしています。
コンソール。
こちらも無事に3回目の出力後に処理は停止しています。
注意点としては、finished の時間が約6秒となっている事です。
setTimeoutの場合、ソースコード末尾でファンクションを呼び出していますが、この最初の呼び出しでは3000ミリ秒の待機を行いません。
そのため、2回目と3回目の待機(3秒*2回)のみが存在するかたちになります。
まとめ的な。
以上の話をまとめると、こうなります(※筆者推測)。
・setInterval()
前後の処理に関わらず、独立して指定時間ごとに実行。
つまり、起動間隔の指定。
ユーザ操作などが必要ない機械的なループに適する。
内部の処理が重過ぎると、スタックオーバーフローの危険性がある。
・setTimeout()
基本的には、引数に与えた関数を、指定ミリ秒後に実行する形(シンタックス参照)。
つまり、待機時間の指定。
前後の処理を考慮するので、スタックオーバーフローの危険性は極めて低い。
調べ始めた時に中々理解できず、納得するまで続けていたらゲームの進捗が遅れたのは内緒です。
今回はここまで。