エラー処理
14.3.1. HTTPステータスコード別処理
- APIレスポンスエラーはHTTPステータスコードを基準に分類して処理します。
- 各ステータスコードに対する処理戦略を事前に定義し、一貫して適用しなければなりません。
| ステータスコード | 意味 | 処理戦略 |
|---|---|---|
| 400 | 不正なリクエスト | サーバーレスポンスのバリデーションメッセージをユーザーに表示します |
| 401 | 認証失敗 | トークン更新を試みます。更新失敗時はログインページにリダイレクトします |
| 403 | 権限なし | アクセス権限不足の案内メッセージを表示します |
| 404 | リソースなし | リクエストされたデータが見つからないことを案内します |
| 409 | 競合 | データ競合状況を案内し、リロードを促します |
| 422 | 処理不可 | サーバーバリデーション失敗メッセージをフォームフィールドにマッピングします |
| 500 | サーバーエラー | 一般的なサーバーエラーメッセージを表示します。詳細内容は公開しません |
| 502/503 | サービス利用不可 | サービスメンテナンスまたは一時的なエラーの案内を表示します |
14.3.2. ネットワークエラー
- サーバーレスポンスがない場合(
error.responseがundefined)はネットワークエラーとして分類します。 - ネットワークエラーとタイムアウトエラーは区別して処理します。
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を使用してエラーを変換します。 - 共通処理が必要な場合はレスポンスインターセプターで変換を実行します。