本記事にはプロモーション(アフィリエイト広告)を含みます。
この記事で分かること
- エラーの種類を分けて原因を調べる方法
- HTTPの成功応答と失敗応答を判定する方法
- fetchとXMLHttpRequestでのエラーの扱いの違い
- 失敗したときに利用者へ伝える画面の作り方
- 再試行やエラー情報を扱うときの注意点
APIを使った情報取得が失敗したとき、何を調べ、画面にどう伝えればよいか迷うことがあります。この記事では、失敗を種類ごとに分け、JavaScriptで確認する方法を説明します。
API(Application Programming Interface)とは、別のプログラムから機能や情報を使うための窓口です。たとえば、天気を表示するページが、天気情報を提供するサービスからデータを受け取るときに使います。
別のプログラムに「この情報をください」「この作業をしてください」と頼むための決まりごとです。
HTTP(Hypertext Transfer Protocol)は、ブラウザーと相手のコンピューターが情報をやり取りするときに使う決まりごとです。以下では、そのやり取りで返される結果を確認します。
ホームページやデータをやり取りするときに、送る側と受け取る側が守る約束です。
エラー処理で大切なのは、失敗をひとまとめにしないことです。相手から返事が来たが内容が失敗を示す場合と、返事自体を受け取れない場合では、確認する場所が異なります。
APIの失敗は3種類に分けて考える
まず、何が起きたかを次の3つに分けます。
| 種類 | 起きていること | 最初に確認すること |
|---|---|---|
| HTTPエラー | 相手から返事は来たが、処理が成功しなかった | 返された番号と、送った内容 |
| 通信の失敗・中断 | 返事を受け取れなかった、または処理を途中で止めた | 接続状況、接続先、処理を止めた理由 |
| JSONの読み取り失敗 | 返事を受け取ったが、期待した形のデータとして読めなかった | 返事の中身と、期待する形式 |
JSON(JavaScript Object Notation)は、データを文字で表す形式です。APIの返事に使われることがありますが、返事がいつもJSONとは限りません。
名前と値を組み合わせて情報を表す、決まった書き方です。たとえば、名前と年齢をまとめて文字で受け渡すときに使えます。
この違いを知っておくと、通信そのものの失敗と、相手から返された失敗の結果を混同せずに済みます。

HTTPステータスは200だけでなく2xxで判定する
HTTPステータスコードは、相手から返される3桁の番号です。200番台は処理が成功したことを示し、400番台や500番台は失敗を示す場合があります。
情報を受け取った側が、処理の結果を伝えるために返す3桁の番号です。
| 番号の例 | 意味の例 | 確認の例 |
|---|---|---|
| 200 | 処理が成功した | 返されたデータを使えるか確認する |
| 201 | 新しいものを作成できた | 作成結果を表示するか確認する |
| 204 | 処理は成功したが、返す内容がない | データを読む処理を続けない |
| 400 | 送った内容に問題がある場合がある | 送った値や入力内容を確認する |
| 401 | 認証が必要、または認証情報に問題がある場合がある | ログイン状態などを確認する |
| 404 | 指定した場所や情報が見つからない | 接続先の指定や対象の有無を確認する |
| 500 | 相手側で処理に問題が起きた場合がある | 相手側の案内や記録を確認する |
2xxは、200から299までの番号をまとめた呼び方です。成功判定を200だけにすると、201や204も失敗として扱ってしまいます。成功かどうかを番号ひとつだけで決めず、返事の内容があるかも確認してください。
200から299までの番号のことです。処理の成功を表しますが、204のように返すデータがない場合もあります。
fetchでHTTPエラー・通信失敗・JSONの読み取り失敗を分ける
fetchは、JavaScriptから相手に情報を求めるための機能です。HTTPエラーの返事を受け取っただけでは、通常、それだけで処理が失敗した扱いにはなりません。返事の状態を自分で確認します。
ページを開き直さずに、別の場所へ情報を求め、返事を受け取るためのJavaScriptの機能です。
次の例では、HTTPの失敗、返事の読み取り失敗、通信処理の失敗を、それぞれ別のメッセージに分けます。
<button id="load-button" type="button">情報を読み込む</button>
<p id="message" role="status"></p>
<pre id="result"></pre>
<script>
const button = document.getElementById("load-button");
const message = document.getElementById("message");
const result = document.getElementById("result");
button.addEventListener("click", loadData);
async function loadData() {
button.disabled = true;
message.textContent = "読み込み中です。";
result.textContent = "";
try {
const response = await fetch(
"https://jsonplaceholder.typicode.com/users/1"
);
if (!response.ok) {
throw new Error(`HTTPエラー: ${response.status}`);
}
let data;
try {
data = await response.json();
} catch (error) {
throw new Error("返事をJSONとして読み取れませんでした。");
}
message.textContent = "読み込みました。";
result.textContent = JSON.stringify(data, null, 2);
} catch (error) {
console.error("情報の読み込みに失敗しました。", error);
message.textContent =
"情報を読み込めませんでした。接続を確認して、もう一度お試しください。";
} finally {
button.disabled = false;
}
}
</script>
asyncとawaitは、返事を待ってから次の処理へ進む書き方です。try/catchは、処理中に起きた問題を受け止める書き方です。
時間のかかる処理の返事を待ち、その後の処理を順番に書くための言葉です。
まず処理を試し、途中で問題が起きたときに別の対応へ進むための書き方です。
awaitは、Promise(プロミス)の結果を待ちます。Promiseは、すぐには終わらない処理について、後から結果を受け取るための仕組みです。
後から結果が分かる作業の受け取り札のようなものです。作業が終わると、成功した結果か失敗した理由を受け取れます。
responseは相手からの返事を表します。response.okがfalseなら、HTTPステータスが成功を示す範囲ではありません。そこでエラーを発生させ、catchへ処理を移しています。
情報を求めたあとに、相手から返ってくる返事です。返事の状態や中身を確認できます。
response.json()は、返事の中身をJSONとして読み取ります。返事がJSONではない場合や、JSONの書き方が正しくない場合は、読み取りに失敗することがあります。
catchに入るのは通信の失敗だけではありません。fetchの処理が拒否された場合や、処理を中断した場合、上の例で発生させたHTTPエラーやJSON読み取りエラーもcatchで受け取ります。
tryの中で問題が起きたときに、後片付けや利用者への案内を行う場所です。
throwは、自分で問題を発生させて、通常の処理を止める書き方です。この例では、HTTPが成功を示さないときにthrowを使っています。
「ここから先の処理は続けられない」として、問題を知らせる書き方です。
コードを試す前提と期待する結果
上の例は、HTMLファイルとして保存し、JavaScriptを実行できるブラウザーで開いて使う形です。外部の接続先にアクセスするため、インターネットへの接続と、接続先がブラウザーからの要求を受け付けることが必要です。
Google ChromeやSafariのように、ホームページを開いて見るためのアプリです。
APIの接続先は、コード中のURLで指定しています。この例は外部サービスを使うため、そのサービスが利用できることを保証するものではありません。
インターネット上のページや情報の場所を示す文字列です。
- コードをHTMLファイルに保存します。
- ブラウザーでファイルを開き、「情報を読み込む」を押します。
- 成功した場合は、読み込み完了の案内と、受け取った情報が表示されます。
- 失敗した場合は、利用者向けの案内が表示されます。詳しい情報は開発者向けのコンソールに記録されます。
上記は期待する結果の説明であり、この環境で実行した検証結果ではありません。ブラウザー名・バージョン、実行日、接続先の応答を確認してから、掲載用の実行結果として確定してください。
XMLHttpRequestでの成功判定とエラー処理
XMLHttpRequest(エックスエムエル・エイチティーティー・リクエスト)は、JavaScriptから情報を送受信する機能です。略してXHRと呼ばれます。fetchとは別の書き方ですが、HTTPエラーの返事が来た場合にも、返事の状態を確認して処理します。
ブラウザーから別の場所へ情報を求め、返事を受け取るための機能です。fetchより前から使われている書き方です。
const xhr = new XMLHttpRequest();
xhr.open("GET", "https://jsonplaceholder.typicode.com/users/1");
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
console.log("成功:", xhr.responseText);
} else {
console.error("HTTPエラー:", xhr.status);
}
};
xhr.onerror = () => {
console.error("通信に失敗しました。");
};
xhr.ontimeout = () => {
console.error("時間内に返事を受け取れませんでした。");
};
xhr.onabort = () => {
console.log("処理を中断しました。");
};
xhr.timeout = 10000;
xhr.send();
onloadは、通信処理が完了したときに呼ばれます。HTTPエラーの返事でも呼ばれるため、statusが200かどうかだけでなく、200以上300未満かを確認します。
onerror、ontimeout、onabortは、それぞれ通信の失敗、制限時間を過ぎた場合、処理を中断した場合を扱います。fetchとXHRのどちらでも、HTTPステータスの確認と、返事を受け取れない場合の対応を分けて考えます。
fetchとXHRの違いを比較する
| 確認すること | fetch | XHR |
|---|---|---|
| HTTPエラーの返事 | 返事を受け取る。okやstatusを確認する | loadが呼ばれる。statusを確認する |
| 通信失敗 | 処理が拒否された場合としてcatchで扱う | errorイベントなどで扱う |
| 中断 | AbortControllerなどを使い、中断をcatchで扱う | abortイベントで扱う |
| 制限時間 | 必要に応じて中断の仕組みを組み合わせる | timeoutを設定し、timeoutイベントで扱う |
| 成功の判定 | okで成功を示す範囲か確認する | statusが200以上300未満か確認する |
どちらを使う場合も、「返事が失敗を示す場合」と「返事を受け取れない場合」を分けて処理します。既存の仕組みがXHRを使っている場合は、動作を理解して適切に判定することが大切です。
よくある失敗と確認方法
- 404が返る:接続先の指定や、求めている情報が存在するかを確認します。
- 400が返る:送った値が接続先の求める形式になっているかを確認します。
- 401が返る:ログイン状態や、接続先が求める認証情報を確認します。
- 500が返る:相手側の処理に問題がある可能性があります。利用者に内部情報を見せず、必要に応じて管理者へ確認します。
- JSONの読み取りに失敗する:返事の内容がJSONか、内容が空ではないか、JSONを読む前提が合っているかを確認します。
- ブラウザーから接続できない:インターネット接続、接続先の設定、アクセス制限などを確認します。
- 処理が長く終わらない:読み込み中の表示と中断方法を用意し、必要なら時間制限を設定します。
CORS(Cross-Origin Resource Sharing)は、別の場所にある情報をブラウザーから受け取るときに、接続先が許可を示すための仕組みです。接続先の許可がないと、ブラウザーが返事をページのJavaScriptへ渡さないことがあります。
あるホームページが、別の場所の情報を読み取ってよいかを、情報を出す側が決める仕組みです。
CORSの問題は、JavaScriptのエラー処理だけで解決できるとは限りません。利用者側で制限を無理に回避せず、接続先の管理者に許可の設定を確認してください。
画面表示・ログ・再試行で気を付けること
利用者には、次に何をすればよいかが分かる案内を表示します。たとえば「情報を読み込めませんでした。接続を確認して、もう一度お試しください」と伝えます。
エラーの詳細は開発者向けの記録に残し、画面には必要以上の情報を出さないようにします。接続先から返された内容や内部の仕組みをそのまま見せると、利用者を混乱させたり、見せる必要のない情報を公開したりするおそれがあります。
再試行ボタンは、失敗した操作を繰り返して問題がない場合に使います。データを作成・変更する処理では、再送によって同じ操作が重複する可能性があるため、結果を確認せずに自動で繰り返さないでください。
AbortController(アボート・コントローラー)は、fetchの処理を中断するために使う機能です。利用者が画面を離れた場合などに処理を止められますが、中断された処理も失敗と同じcatchへ入ることがあるため、利用者が自分で止めたのか、別の失敗なのかを区別します。
fetchで始めた処理を、あとから止めるための仕組みです。
再試行や制限時間の設定は、通信先や操作の内容に合わせて決めます。すべてのエラーを同じ方法で再試行するのではなく、何が起きたかを確認してから対応してください。
公式情報と仕様を確認する
詳しい動作や使える機能は、公式の仕様と利用するブラウザーの情報を確認してください。
- WHATWG Fetch Standard:fetchの仕様
- WHATWG XMLHttpRequest Standard:XMLHttpRequestの仕様
- MDN:AbortController:中断の仕組みの解説
- MDN:HTTPレスポンスステータスコード:番号の意味の解説
この記事の例について、確認したブラウザー名・バージョン・確認日・実行結果は、現時点で人による情報が提供されていません。公開前に環境を記録し、コードと公式仕様を照合してください。
JavaScriptを基礎から学びたい方へ PR
APIのエラー処理だけでなく、JavaScriptの基本や非同期処理も順に学びたい人には、関連分野を広く扱う書籍も選択肢になります。
これからのJavaScriptの教科書
JavaScriptの基本文法から、ページ操作、非同期処理までを扱う書籍です。サンプルコードを試しながら学べる構成として紹介されています。
- 基本から非同期処理まで、順序立てて学びたい人に向いています。
- 対象はECMAScript 2023です。
- 全608ページのため、要点だけを短時間で確認したい人には分量が多く感じられる場合があります。
よくある質問(FAQ)
fetchのHTTPエラーがcatchに入らないのはなぜですか?
HTTPエラーの返事を受け取っただけでは、fetchは通常、処理を失敗として扱わないためです。response.okやresponse.statusを確認し、必要に応じてエラーとして処理します。
成功判定はstatusが200かどうかだけでよいですか?
200だけで判定すると、201や204を成功として扱えません。fetchではok、XHRでは200以上300未満かを確認し、返事にデータがあるかも考慮します。
fetchのcatchには通信の失敗だけが入りますか?
いいえ。通信の失敗のほか、中断などで処理が拒否された場合や、自分で発生させたエラーも入ります。エラーの内容に応じて対応を分けてください。
204が返ったときにJSONを読めますか?
204は成功を示しますが、返す内容がありません。JSONを読む処理を続けず、接続先の仕様に合わせて分岐してください。
失敗したら、毎回自動で再試行してよいですか?
毎回の自動再試行は避けてください。データを作成・変更する操作では、同じ処理が重複する可能性があります。操作の内容と失敗理由を確認してから再試行します。
まとめ
- HTTPエラー、通信の失敗、中身の読み取り失敗を分けて考える
- fetchではHTTPの返事を受け取ったあと、okやstatusを確認する
- XHRではstatusが200以上300未満かを確認する
- 204のように返すデータがない成功応答に注意する
- 利用者への案内と詳しい記録を分け、再試行は操作の内容を見て判断する
次は、処理を待つ仕組みやデータの表示方法を学ぶと、APIを使った画面作りへの理解が深まります。
JavaScript全体の学習順序は、JavaScript ロードマップ|基礎からDOM・イベント・フォーム操作まで体系的に学ぶガイドから確認できます。