JavaScriptのfetchでデータを取得しているのに、存在しないURLを指定してもcatchへ進まないことがあります。HTTPの404は、通信の仕組みとして応答が返った状態だからです。画面で成功と失敗を分けるには、応答のHTTP状態も確かめます。
response.okは200番台の応答ならtrueになります。ただし、200でもJSONが壊れていたり、必要な項目がなかったりする場合があります。通信、HTTPの状態、JSONの解析、データの条件を順に分けて扱います。
HTTPとデータの条件を確認する
次の関数は練習用のJSONから0以上の整数の件数を読む例です。fetcherという引数を使うと、練習では取得結果を代用して分岐を確認できます。省略した場合はブラウザのfetchを使います。
async function readCount(fetcher = fetch) {
const response = await fetcher('./practice-data.json');
if (!response.ok) {
throw new Error('HTTP ' + response.status);
}
const data = await response.json();
if (!data || !Number.isSafeInteger(data.count) || data.count < 0) {
throw new Error('件数の形式を確認してください');
}
return data.count;
}
練習用のpractice-data.jsonは{"count":3}という内容です。正常時は3を返します。{"count":"3"}は文字列なので、この関数では受け付けません。数値へ勝手に変換せず、APIが返す形式と期待する形式が一致しているかを確かめます。
HTMLへ組み込むときは、次のように呼びます。失敗時に前回の成功表示を残さず、結果を確認できなかったことを伝えます。
async function showCount(output) {
output.textContent = '件数を取得中です。';
try {
const count = await readCount();
output.textContent = count + '件を取得しました。';
} catch (error) {
output.textContent = '取得できません。応答と入力条件を確認してください。';
console.error(error.message);
}
}
これはGETによる読み取りの例です。投稿や申請の保存を行うコードではありません。画面へ出す説明は利用者向けにし、調査に必要なHTTP状態や解析エラーは、秘密を含めないログで確認できる形にします。
404と通信失敗の見え方
404や500なら、fetchは応答を返してもokがfalseになります。存在しないホストなどの通信失敗では、fetch自体が拒否される場合があります。さらに、HTMLのエラーページを200で返すサーバーでは、response.json()で解析に失敗する場合があります。
そのため「HTTPが200だった」だけで、期待したデータを受け取れたとは判断しません。応答の内容がJSONで、その中のcountがこの例の条件に合うかまで確かめます。実際のAPIでは配列の構造や必須IDなど、後続処理が必要とする条件へ置き換えます。
ローカルファイルのまま開かない
file:から開いたHTMLで別ファイルを取得すると、ブラウザの制約によって失敗する場合があります。練習用フォルダーにHTMLとJSONだけを置き、そのフォルダーでpython -m http.server 8000 --bind 127.0.0.1を実行すれば、ローカルのHTTPで試せます。開く先はhttp://127.0.0.1:8000/です。
配信されるのは実行したフォルダーの内容なので、練習用のファイルだけにします。ここでの分岐確認はブラウザ内の代用応答による正常、404、不正JSON、形式違い、通信失敗の確認です。実サービスの障害や権限まで再現した結果ではありません。
関連する記事
UrlFetchAppで外部APIを呼び出す方法|GET/POSTの基本
