Skip to content

エラー処理

14.3.1. HTTPステータスコード別処理

  • APIレスポンスエラーはHTTPステータスコードを基準に分類して処理します。
  • 各ステータスコードに対する処理戦略を事前に定義し、一貫して適用しなければなりません。
ステータスコード意味処理戦略
400不正なリクエストサーバーレスポンスのバリデーションメッセージをユーザーに表示します
401認証失敗トークン更新を試みます。更新失敗時はログインページにリダイレクトします
403権限なしアクセス権限不足の案内メッセージを表示します
404リソースなしリクエストされたデータが見つからないことを案内します
409競合データ競合状況を案内し、リロードを促します
422処理不可サーバーバリデーション失敗メッセージをフォームフィールドにマッピングします
500サーバーエラー一般的なサーバーエラーメッセージを表示します。詳細内容は公開しません
502/503サービス利用不可サービスメンテナンスまたは一時的なエラーの案内を表示します

14.3.2. ネットワークエラー

  • サーバーレスポンスがない場合(error.responseundefined)はネットワークエラーとして分類します。
  • ネットワークエラーとタイムアウトエラーは区別して処理します。
typescript
// src/api/utils/error.ts
import type { AxiosError } from 'axios'

export function isNetworkError(error: AxiosError): boolean {
  return !error.response && error.code !== 'ECONNABORTED'
}

export function isTimeoutError(error: AxiosError): boolean {
  return error.code === 'ECONNABORTED'
}
  • オフライン状態の検出にはnavigator.onLineプロパティとonline/offlineイベントリスナーを活用します。
  • Composable関数(useNetworkStatus)として実装し、コンポーネントでリアクティブに使用します。

14.3.3. ユーザーフィードバック

  • APIエラー発生時、ユーザーに適切なフィードバックを提供しなければなりません。
  • エラーメッセージは標準化された形式で管理します。
typescript
// src/api/utils/notify.ts
const ERROR_MESSAGES: Record<string, string> = {
  NETWORK_ERROR: 'ネットワーク接続を確認してください。',
  TIMEOUT_ERROR: 'リクエストがタイムアウトしました。再度お試しください。',
  UNAUTHORIZED: '認証が期限切れです。再度ログインしてください。',
  FORBIDDEN: 'アクセス権限がありません。',
  NOT_FOUND: 'リクエストされたデータが見つかりません。',
  SERVER_ERROR: 'サーバーエラーが発生しました。しばらくしてから再度お試しください。',
  DEFAULT: 'エラーが発生しました。',
}

export function getErrorMessage(code: string): string {
  return ERROR_MESSAGES[code] ?? ERROR_MESSAGES.DEFAULT
}
  • サーバーから送信されるエラーメッセージがある場合、そのメッセージを優先的に使用します。
  • サーバーメッセージがないか技術的な内容の場合、標準メッセージに置き換えます。

14.3.4. グローバルエラーハンドラー

  • Axiosエラーをアプリケーション標準エラーオブジェクトに変換するハンドラーを実装します。
  • AppErrorクラスを定義してエラー型を統一します。
typescript
// src/api/errors/AppError.ts
export class AppError extends Error {
  readonly status: number
  readonly code: string

  constructor(status: number, code: string, message: string) {
    super(message)
    this.name = 'AppError'
    this.status = status
    this.code = code
  }
}
typescript
// src/api/errors/handleApiError.ts
import type { AxiosError } from 'axios'
import { AppError } from './AppError'
import { isNetworkError, isTimeoutError } from '@/api/utils/error'

export function handleApiError(error: AxiosError): AppError {
  if (isTimeoutError(error)) {
    return new AppError(0, 'TIMEOUT_ERROR', 'リクエストタイムアウト')
  }
  if (isNetworkError(error)) {
    return new AppError(0, 'NETWORK_ERROR', 'ネットワークエラー')
  }

  const status = error.response?.status ?? 0
  const data = error.response?.data as Record<string, string> | undefined

  return new AppError(status, data?.code ?? 'UNKNOWN_ERROR', data?.message ?? '不明なエラー')
}
  • 個別のAPI呼び出しでhandleApiErrorを使用してエラーを変換します。
  • 共通処理が必要な場合はレスポンスインターセプターで変換を実行します。

TIENIPIA QUALIFIED STANDARD