2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaScriptにおけるエラーハンドリング設計:try/catch・例外境界・ログとユーザー通知の分離戦略

Posted at

概要

エラーハンドリングとは、「例外を防ぐこと」ではない。
それは「例外が起きたときに、どう受け止め、誰に、どう伝えるか」の設計である。

本稿では以下の視点から、実用的なエラーハンドリングの設計を体系化する:

  • try/catchの設置場所と粒度
  • 例外のログと通知の分離
  • 再スローと再試行の設計
  • エラー分類とユーザーへの伝え方
  • グローバルエラーバウンダリと復旧戦略

1. try/catchの基本構造と設計思想

try {
  const data = await fetchData();
  render(data);
} catch (e) {
  showError(e.message);
}
  • ✅ catchブロックでは必ずログ + UI通知を行う
  • ❌ 空のcatchは絶対NG(例外を握り潰す)

2. catchブロックの責務分離

try {
  await riskyProcess();
} catch (e) {
  logError(e);       // ✅ 開発者用ログ
  notifyUser(e);     // ✅ ユーザー用メッセージ
}
  • 開発者向けログは詳細に
  • ユーザー通知は簡潔に(不安にさせない)

3. エラーの種類と対応の分離

エラー分類 ユーザー対応
ユーザー操作系 入力ミス、無効な値 明確なバリデーションで制御
ネットワーク系 タイムアウト、サーバーダウン 再試行・リトライ導線
アプリ側バグ 未定義変数、null参照など ログ + 通知 + 再発防止
想定外例外 外部ライブラリ、型不一致など フォールバック設計が必要

4. 再スローと例外の巻き取り

function loadData() {
  try {
    return fetchData();
  } catch (e) {
    logError(e);
    throw e; // ✅ 呼び出し元に“委譲”する
  }
}
  • ✅ 例外をログしてそのまま再スロー
  • ✅ UIで通知したい場合は“最上位”で巻き取る

5. グローバルエラーキャッチと設計境界

✅ 未処理のPromiseを拾う

window.addEventListener('unhandledrejection', (e) => {
  logError(e.reason);
});

✅ 実行時エラーのキャッチ

window.addEventListener('error', (e) => {
  logError(e.message);
});

→ ✅ あくまで最終防波堤として設置する(ローカルで拾うのが原則)


6. UI通知のパターン化

  • ✅ トースト:軽微な失敗(再試行可能)
  • ✅ モーダル:致命的な失敗(UIをブロック)
  • ✅ インライン:フォームエラーや局所的な問題
notifyUser('保存に失敗しました。もう一度お試しください。');

→ ✅ 文言は“冷静・簡潔・解決策を含む”ことが理想


7. エラーをデザインする:コード例

try {
  await saveData(formInput);
  showSuccess('保存しました');
} catch (e) {
  if (e instanceof ValidationError) {
    showFormErrors(e.details);
  } else if (e instanceof NetworkError) {
    showToast('通信に失敗しました。再試行してください。');
  } else {
    logError(e);
    showError('予期せぬエラーが発生しました');
  }
}

→ ✅ 独自エラー型による分類設計が有効(class ValidationError extends Error など)


設計判断フロー

① この処理は失敗し得る? → try/catch設置

② 失敗時に伝えるべき情報は? → log + notify に分離

③ 呼び出し元に伝えるべき? → throwを再スロー

④ 再試行できる? → retry戦略とUI導線を設計

⑤ 想定外の例外? → グローバルcatchでログと復旧設計

よくあるミスと対策

❌ catchしたエラーを握り潰す

→ ✅ 必ずログかユーザー通知へつなげる


❌ すべてのエラーに同じ通知

→ ✅ エラーの種類ごとにUI反応を設計する


❌ グローバルエラーでしか検知できない

→ ✅ 例外境界を意識し、局所で明示的に処理する


結語

“エラー処理”とは、例外を潰すことではない。
それは、アプリケーションが“壊れないように、正しく壊れる”ための構造設計である。

  • 捕まえる場所を設計する
  • 伝える内容を整理する
  • ログとUIを分けて考える
  • 状態を破壊しないよう巻き取る
  • 再試行やフォールバックを明示する

優れたエラーハンドリングは、ユーザーと開発者の両方を救う設計資産である。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?