setInterval を一言でいうと何か
setInterval は
「この処理を◯ミリ秒ごとにくり返し実行してね」とブラウザ(または Node)に頼む関数
です。
setTimeout が「1回だけ、あとで実行」なのに対して、setInterval は「一定間隔で何度も実行」するための仕組みです。
ただし、仕組みの根っこはほぼ同じで、
- 「時間を測る」のは JavaScript 本体ではなく Web API
- 実行するときは、コールバックをタスクキューに入れてイベントループが拾う
という流れです。
ここが重要です。
setInterval は「一定間隔でタスクキューにコールバックを投げ続けるタイマー」 だとイメージしてください。
「間隔ぴったりで実行される魔法」ではありません。
setInterval の基本的な使い方と動き
もっともシンプルな例
let count = 0;
const id = setInterval(() => {
count++;
console.log("カウント:", count);
}, 1000);
JavaScriptこのコードは、
- 約 1 秒ごとに
"カウント: 1","カウント: 2","カウント: 3"…と表示し続けます。 setIntervalは「タイマー ID」を返してくるので、それを変数idに保存しています。
止めたいときは clearInterval(id) を呼びます。
setTimeout(() => {
clearInterval(id);
console.log("停止しました");
}, 5000);
JavaScriptこれで約 5 秒後にくり返しが止まります。
引数の意味
setInterval(コールバック関数, 間隔ミリ秒, 追加引数1, 追加引数2, ...)
- 第1引数:毎回実行されるコールバック関数
- 第2引数:2 回目以降の「実行の間隔」(ミリ秒)
追加引数はほぼ使われませんが、指定するとコールバックの引数として渡されます(昔の仕様)。
初心者のうちは、第1・第2引数だけ覚えれば十分です。
setInterval の裏側で何が起きているか
1回の実行の「サイクル」
シンプルに言うと、1 回ごとの流れはこうです。
- Web API に「◯ミリ秒ごとにこのコールバックを実行して」と依頼する(
setInterval呼び出し) - Web API 側のタイマーが「時間経過」を監視する
- 指定時間が経過するたびに、「このコールバックをタスクキューに入れて」とイベントループ側に渡す
- イベントループが、コールスタックが空いたタイミングでそのコールバックを実行する
これが、間隔ごとに何度もくり返される だけです。
ここでのポイントは、
- 時間を測っているのは Web API(JavaScript 本体じゃない)
- 実行タイミングは「スタックが空いたとき」の都合に依存する
という 2 つです。
setTimeout との違い(1回 vs 何回も)
setTimeout は「1 回だけ」タスクキューにコールバックを投げて終わりですが、setInterval は「指定した間隔ごとに何度も」タスクキューにコールバックを投げ続けます。
イメージとしては、
- setTimeout:一回だけ鳴る目覚まし
- setInterval:一定間隔で鳴り続けるアラーム
の違いに近いです。
「間隔ぴったり」ではない理由(ここを勘違いしがち)
実行されるのは「指定時間が経ったあと+JS側のタイミング次第」
例えば次のコードを考えてみます。
setInterval(() => {
console.log("tick", Date.now());
}, 1000);
JavaScriptこれは「おおよそ 1 秒ごと」に tick を出しますが、
ぴったり 1000ms ごと ではありません。
理由は、
- Web API は 1000ms ごとに「コールバックをキューに入れていいよ」と準備する
- しかし、コールスタックが忙しい(重い処理中など)と、イベントループはすぐにそれを実行できない
- 結果として「1000ms 経過した時点」ではなく、「1000ms 経過していて、かつ JS が暇になったタイミング」でコールバックが走る
からです。
例えば、間に重い処理が挟まるとこうなります。
setInterval(() => {
console.log("tick", Date.now());
}, 1000);
const start = Date.now();
while (Date.now() - start < 5000) {
// 5秒間重い処理
}
JavaScriptこの 5 秒間、イベントループは新たなタスクを実行できません。
その間に「何回分も tick がキューに溜まる」こともありますが、
実際に実行されるのは while が終わってからです。
ここが重要です。
setInterval の引数は「実行間隔を保証する値」ではなく、「このくらいの間隔で“実行候補をキューに入れる目安”」 だと理解してください。
setInterval の ID と clearInterval の仕組み
なぜ ID が返ってくるのか
const id = setInterval(...); のように書くと、id には「タイマーを識別する番号」が入ります。
裏側では、
setIntervalが呼ばれるたびに、ブラウザは「新しいタイマーオブジェクト」を作る- それぞれに固有の ID がつく
clearInterval(id)とすると、その ID に対応するタイマーを止める
という動きになっています。
let count = 0;
const id = setInterval(() => {
count++;
console.log(count);
if (count >= 3) {
clearInterval(id);
console.log("停止");
}
}, 1000);
JavaScriptこのコードでは、
- 1秒ごとに 1, 2, 3 と出力
- 3 回目が終わったところで
clearInterval(id)によってタイマーが停止
という流れになります。
setInterval と setTimeout の実践的な違い
「setInterval でループ」 vs 「再帰的 setTimeout」
setInterval は一見便利ですが、
「処理時間を考慮しない」ために、場合によっては望ましくないことがあります。
setInterval(() => {
// ここが思ったより時間のかかる処理
}, 1000);
JavaScriptこの処理が 900ms かかるとすると、
- 1000ms ごとに新しい実行がキューに乗る
- しかし前の処理がまだ終わっていないかもしれない
- 最悪、処理が重すぎて「前の処理が終わらないうちに次の tick が溜まり続ける」
といった状態になります。
一方、「再帰的 setTimeout」ならこうなります。
function tick() {
const start = Date.now();
// 時間のかかる処理(仮)
while (Date.now() - start < 900) {}
console.log("tick at", Date.now());
setTimeout(tick, 1000);
}
setTimeout(tick, 1000);
JavaScriptこれは、
- 処理を 1 回実行する
- 終わった「あと」で、1 秒待ってから次を実行する
という形になるので、
「処理時間+待ち時間」で間隔が決まる」=「処理が重くても詰まりにくい」
という特徴があります。
ここが重要です。
「必ず◯ms ごとに実行したい」のか、「1回の処理が終わってから◯ms 休んで次に行きたい」のかで、setInterval と再帰的 setTimeout で向いている場面が違う ということです。
初心者として押さえておきたい setInterval のポイント
どこまで理解しておけばいいか
今の段階で、次の感覚があれば十分です。
setInterval は「◯ミリ秒ごとにコールバックをタスクキューに投げるタイマー」である。
タイマーの管理(時間を測る)は Web API が行い、実際の実行はイベントループとタスクキューに任される。
指定した間隔は「ぴったりその時間で実行する」のではなく、「その時間ごとに“実行候補”をキューに入れる」イメージである。
返り値の ID を clearInterval に渡すことで、タイマーを止めることができる。
処理が重い場合や、前の処理の終了を待ってから次を実行したい場合は、「再帰的 setTimeout」のほうが設計しやすい場合がある。
簡単な練習のアイデア
理解を定着させるために、次のような小さなコードを書いてみると良いです。
秒数をカウントし続けるタイマー(1秒ごとに表示)を setInterval で作る
一定回数で自動停止するタイマーを作る(clearInterval を使う)
同じ処理を setInterval と 再帰的 setTimeout で書き、重い処理を入れて違いを感じてみる
このあたりを試すだけで、
「setInterval は『定期的にタスクキューに仕事を投げる仕組み』なんだな」
という実感がかなりはっきりしてきます。
まとめ
setInterval の本質を一文でまとめると、
「指定した間隔ごとに、コールバック関数をタスクキューに追加し続けるタイマー API」
です。
そこに、
時間を測るのは Web API
実際に実行するタイミングを決めるのはイベントループ
実行の順番・タイミングはタスクキューやコールスタックの状況に依存
という非同期の仕組みが関わっています。
ここまでの理解があると、
- 「なぜ interval の間隔がズレるのか」
- 「なぜ clearInterval が必要なのか」
- 「なぜ場合によっては再帰的 setTimeout が好まれるのか」
といった疑問にも、自分で説明がつくようになります。
setTimeout の仕組みと合わせて頭に入れておくと、
JavaScript の「時間を扱う非同期処理」がかなりクリアに見えてきます。
