タイムアウト
Timeout
タイムアウトとは、一定の時間を超えたら待機を打ち切り、失敗や再試行の判断へ進む仕組みです。待つ側を解放することと、相手側の処理を取り消すことは同じではありません。
🐾 猫で例えると?
カエルの被り物で両手を伸ばし、ヘッドスライディングの途中のように眠る茶トラ。「遊ぼう」と返事を待つ飼い主も、「30秒待って起きなければ、また後にしよう」と区切りを決めたら、その待機の打ち切りがタイムアウトです。返事を待つ時間に上限を設け、待つ側が次へ進む点が対応します。
💻 IT現場における「タイムアウト」とは?
外部サービスの応答を長く待つと、接続や処理枠が埋まり、他の要求にも影響する場合があります。OSや通信ライブラリーに既定値があっても、利用者が待てる時間やサービス全体の期限に合うとは限らないため、目的に合わせて設定します。
眠る茶トラに呼びかけても返事がないとき、飼い主は決めた時間で「今回は諦めて後で様子を見よう」と待つのを切り上げますよね。システムも同じで、「〇秒待って返事がなければエラーとして次に進む」という制限時間を明確に決めておくことで、1つのトラブルが全体に波及するのを防いでいるのです。
⚠️ タイムアウトの仕組みと注意点
接続を確立するまでの期限、データの受信が止まっている時間、処理全体の期限などがあります。ライブラリーによって設定項目の意味が違うため、「5秒」がどこからどこまでかを確認します。
JavaScriptでのタイムアウト実装例(fetch API)
fetchにはtimeoutという引数はありません。AbortControllerで中断するほか、対応環境ならAbortSignal.timeoutも使えます。次はJSON本文の読み取りまでタイマーを残し、成功・失敗のどちらでも片付ける例です。
async function fetchJsonWithTimeout(url, timeoutMs = 5000) {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), timeoutMs);
try {
const response = await fetch(url, { signal: controller.signal });
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return await response.json();
} finally {
clearTimeout(timer);
}
}
// fetchとAbortControllerがある環境で使用する。
// 呼び出し側で例外を扱い、画面へ失敗や再試行の案内を表示する。 ブラウザーのタイマーはメインスレッドの長い処理などで遅れる場合があり、厳密な実行時間の保証ではありません。また通信を中断しても、サーバーがすでに受け付けた注文や保存が取り消されるとは限りません。
🛠️ タイムアウトを賢く設計するためのポイント
現場でタイムアウトを設計する際にエンジニアが気を付けるべきポイントです。
- 短すぎず、長すぎない絶妙な時間設定: タイムアウトが短すぎると、少し通信が遅延しただけで正常なユーザーまでエラー弾きしてしまいます。逆に長すぎるとシステムの貴重なリソース(メモリや接続枠)を無駄に消費し続けるため、APIの特性に合わせた適切な秒数(例:3秒〜10秒)を見極める必要があります。
- 再試行できる操作か確認する:取得処理と、注文・決済などの更新処理では扱いが異なります。結果が不明な更新を無条件に再送せず、処理IDによる確認や冪等性を設計します。再試行回数と待ち時間にも上限を設けます。
- ユーザーへの親切なフィードバック: タイムアウトで処理が失敗した際は、「しばらく経ってからもう一度お試しください」といった分かりやすいメッセージを画面に出し、ユーザーを不安にさせない工夫が重要です。
眠る茶トラから返事が来ないように、応答が止まって見えても、相手側の処理が終わっていないとは限りません。タイムアウト後は、再試行しても重複しない操作か、先の処理結果を確認できるかを判断します。画面にも「何が分からず、次に何ができるか」を伝えましょう。