取消可能タイマーの基本 — const id = setTimeout(...); clearTimeout(id)
「一定時間後に一度だけ実行」するのが setTimeout。その実行予約はタイマーIDで管理でき、必要なくなったら clearTimeout(id) で取り消せます。UIやページ遷移時の後処理、誤タップ対策などで必須の基礎テクです。
基本の使い方
// 3秒後にメッセージ表示を予約
const id = setTimeout(() => {
console.log("3秒経過");
}, 3000);
// 予約を取り消す
clearTimeout(id);
JavaScript- タイマーID:
setTimeoutの戻り値。これを保存しておけば後でキャンセル可能。 - 取り消しの瞬間: 指定時間「前」に
clearTimeout(id)が呼ばれれば、コールバックは実行されない。
よく使うテンプレート集
遅延表示のキャンセル(ユーザー操作で止める)
let tid = null;
function scheduleHint() {
tid = setTimeout(() => showHint("ここをクリック"), 2000);
}
function cancelHint() {
if (tid) clearTimeout(tid);
}
// 例: 入力が始まったらヒントを出さない
input.addEventListener("focus", cancelHint);
JavaScript- ラベル: 直前に「出す予定」にしていても、操作が入れば取り消す。
ページ遷移やクリーンアップ時に止める
let tid = setTimeout(fetchAndRender, 5000);
// SPAの画面から離れる直前
function onLeavePage() {
clearTimeout(tid); // 古い画面用の処理が走らないように
}
JavaScript- ラベル: 古い画面に紐づく処理は撤収。副作用の暴発を防ぐ。
ボタンで開始・停止(初心者向け鉄板)
let tid = null;
startBtn.onclick = () => {
tid = setTimeout(() => alert("5秒経過"), 5000);
};
stopBtn.onclick = () => {
if (tid) clearTimeout(tid);
};
JavaScript- ラベル: IDをスコープに保持し、いつでも
clearTimeout。
再帰的な setTimeout の安全停止
let tid = null;
let count = 0;
function tick() {
console.log("tick", ++count);
if (count < 5) tid = setTimeout(tick, 1000);
}
tid = setTimeout(tick, 1000);
// 途中でやめたい場合
stopBtn.onclick = () => clearTimeout(tid);
JavaScript- ラベル: 次回予約のIDを更新しておけば、最新の予約を止められる。
実務でのパターンとコツ
- ラベル:IDの管理場所
- ポイント: コンポーネントやクラスのフィールド(またはクロージャ変数)に保持。複数あるなら配列に入れて一括停止。
- ラベル:ダブル予約防止
- ポイント: 新規予約前に
clearTimeout(tid)を呼んでから再設定する(重複実行を避ける)。
- ポイント: 新規予約前に
if (tid) clearTimeout(tid);
tid = setTimeout(run, 1000);
JavaScript- ラベル:非同期と組み合わせる
- ポイント: タイムアウトの実装は
Promise.raceでも可能だが、UIの簡易遅延や演出にはsetTimeoutとclearTimeoutが手軽。
- ポイント: タイムアウトの実装は
- ラベル:メモリ・副作用対策
- ポイント: 画面破棄・Unmount・イベント解除時に必ず
clearTimeout。予期せぬ実行で古いDOMを触るバグを防ぐ。
- ポイント: 画面破棄・Unmount・イベント解除時に必ず
ありがちなハマりポイントと対策
- ラベル:タイマーIDを取り違える
- 症状: 別のIDを止めようとしてキャンセルできない。
- 対策: 予約直後に必ず保存。複数IDは名前を付ける(例:
hintTid,fetchTid)。
- ラベル:予約の上書き忘れ
- 症状: 連打でタイマーが複数生まれ、同じ処理が何度も走る。
- 対策: 新規予約前に必ず
clearTimeoutしてから再予約。
- ラベル:スコープから消える
- 症状:
const idがローカルにあって外から止められない。 - 対策: 停止が必要な範囲でIDを共有(フィールドや外側スコープ)。
- 症状:
- ラベル:ミリ秒単位の勘違い
- 症状: 1秒を 1 と書いて何も起きない。
- 対策: 1000ms = 1秒。人間の秒をミリ秒に直す癖をつける。
練習問題(手を動かして覚える)
// 1) 3秒後の実行を1秒後にキャンセル
const id1 = setTimeout(() => console.log("実行される?"), 3000);
setTimeout(() => clearTimeout(id1), 1000);
// 2) 連打でも常に最新だけが有効(前回はキャンセル)
let tid2 = null;
function scheduleOnce() {
if (tid2) clearTimeout(tid2);
tid2 = setTimeout(() => console.log("最新の予約が実行"), 1000);
}
scheduleOnce(); scheduleOnce(); scheduleOnce(); // 最後の1回のみ
// 3) 再帰的setTimeoutを3回で停止
let tid3 = null, n = 0;
function repeat3() {
console.log("tick", ++n);
if (n < 3) tid3 = setTimeout(repeat3, 500);
}
tid3 = setTimeout(repeat3, 500);
// 4) ボタンクリックで開始→もう一度クリックで停止(トグル)
let tid4 = null;
function toggleTimer() {
if (tid4) { clearTimeout(tid4); tid4 = null; console.log("停止"); }
else { tid4 = setTimeout(() => { console.log("実行"); tid4 = null; }, 2000); }
}
JavaScript直感的な指針
- 予約したらIDを持つ。止めたいときは
clearTimeout(id)。 - 新規予約前に前回をキャンセルして「最新だけ」を生かす。
- 画面破棄・遷移・ユーザー操作で不要になったら、確実に止める。
