HOME / BLOG
BLOG

JavaScriptのfetchにタイムアウトを付ける方法【AbortSignal.timeout】

デフォルト画像

JavaScriptのfetch()は手軽ですが、何も考えずに使うと、通信が返ってこないときの扱いが曖昧になります。実務のUIでは、読み込み中のまま止まる、再試行できない、エラー内容が分からない、という状態を避けたいところです。

この記事では、AbortSignal.timeout()を使ってfetch()にタイムアウトを付ける基本形をまとめます。

まず押さえること

  • fetch()はHTTP 404や500だけでは例外にならない
  • response.okで成功扱いにしてよいか確認する
  • タイムアウトはAbortSignal.timeout()で付けられる
  • 古い環境も見るならAbortControllersetTimeoutのフォールバックを用意する

AbortSignal.timeout()を使う

async function fetchJson(url, options = {}) {
  const timeout = options.timeout ?? 5000;
  const signal = AbortSignal.timeout(timeout);

  const response = await fetch(url, {
    headers: {
      Accept: 'application/json',
      ...options.headers,
    },
    signal,
  });

  if (!response.ok) {
    throw new Error(`HTTP error: ${response.status}`);
  }

  return response.json();
}

try {
  const data = await fetchJson('/api/articles', { timeout: 8000 });
  console.log(data);
} catch (error) {
  if (error.name === 'TimeoutError') {
    console.error('通信がタイムアウトしました');
  } else if (error.name === 'AbortError') {
    console.error('通信が中断されました');
  } else {
    console.error(error.message);
  }
}

古い環境向けのフォールバック

AbortSignal.timeout()は便利ですが、古いブラウザまで強く見る場合は、AbortControllersetTimeoutで同じような形を作れます。

async function fetchJsonWithFallbackTimeout(url, options = {}) {
  const timeout = options.timeout ?? 5000;
  const controller = new AbortController();
  const timerId = setTimeout(() => controller.abort(), timeout);

  try {
    const response = await fetch(url, {
      headers: {
        Accept: 'application/json',
        ...options.headers,
      },
      signal: controller.signal,
    });

    if (!response.ok) {
      throw new Error(`HTTP error: ${response.status}`);
    }

    return response.json();
  } finally {
    clearTimeout(timerId);
  }
}

UI側で分けたい状態

状態表示例
loading読み込み中のスピナーを出す
success取得したデータを表示する
timeout通信が混み合っています。再試行してください。
http errorデータの取得に失敗しました。
abort通信を中断しました。

WordPressや小さなAPIで使うなら

WordPress REST APIや自作APIを読むときも、タイムアウトとresponse.okのチェックを入れておくと、エラーの切り分けが楽になります。特にアクセス解析ダッシュボードやランキング表示のように、画面表示がAPIに依存する機能では最初から入れておきたい処理です。

あわせて読みたい

参考資料

まとめ

fetch()を使うなら、通信成功、HTTPエラー、タイムアウト、中断を分けて扱うだけで、UIの信頼感が上がります。小さな個人開発でも、APIを読む処理には最初からタイムアウトを入れておくのがおすすめです。