【JS応用|実務向け】モダンフロントエンド開発におけるfetch APIの正しい扱い方と実装パターン

導入

現代のフロントエンド開発において、サーバーとの非同期通信は避けて通れません。以前はXMLHttpRequestが主流でしたが、現在は標準APIであるfetchが広く使われています。しかし、fetchは「Promiseを返すだけで、HTTPエラー(404や500など)ではrejectされない」という特性があり、安易に使うと予期せぬバグを生む原因になります。本記事では、実務で安全にfetchを扱うための実装パターンを解説します。

基礎知識

fetch APIは、Webブラウザに標準搭載されたネットワークリクエスト用インターフェースです。Promiseベースで設計されており、async/await構文と組み合わせることで、直感的に非同期処理を記述できます。重要な点として、fetchはリクエストがネットワークエラー(DNS解決失敗など)にならない限り、HTTPステータスコードが何であれ「成功」として扱います。そのため、レスポンスのokプロパティを確認する処理が必須です。

実装/解決策

実務では、fetchを直接呼び出すのではなく、エラーハンドリングを共通化したラッパー関数を作成するのが定石です。これにより、毎回if文でステータスチェックを行う手間を省き、コードの保守性を高めます。また、TypeScriptを利用している場合は、レスポンスの型定義をジェネリクスで受け取れるように設計すると、型安全な通信が可能になります。

サンプルプログラム

以下のコードは、実務でそのまま利用可能な、エラーハンドリングを備えた汎用的なfetchラッパーの例です。

/
  • fetchをラップした汎用APIクライアント
  • @param url 取得先のURL
  • @param options リクエストオプション
/ async function apiClient<T>(url: string, options: RequestInit = {}): Promise<T> { const response = await fetch(url, options); // 1. HTTPステータスが200-299の範囲外であればエラーを投げる if (!response.ok) { throw new Error(`HTTP Error: ${response.status} - ${response.statusText}`); } // 2. JSONとしてパースして返す return response.json() as Promise<T>; } // 使用例 interface User { id: number; name: string; } async function fetchUserData() { try { const user = await apiClient<User>('/api/user/1'); console.log('ユーザー名:', user.name); } catch (error) { // 通信エラーやHTTPエラーをここで一括キャッチ console.error('通信に失敗しました:', error); } }

応用・注意点

現場で陥りやすい注意点が2つあります。1つ目は「タイムアウト処理」です。fetch単体にはタイムアウト機能がないため、AbortControllerを併用して一定時間後にリクエストをキャンセルする仕組みを実装することを推奨します。2つ目は「CORS(Cross-Origin Resource Sharing)」です。異なるドメインへのリクエストを行う場合、サーバー側で適切なレスポンスヘッダーが設定されていないと通信が拒否されます。ブラウザのコンソールエラーを確認し、必要に応じてリクエスト時のmode設定などを調整してください。これらを網羅することで、堅牢なAPI通信を実現できます。

タイトルとURLをコピーしました