Day 4・非同期とfetchでAPIを叩く
エラーハンドリング(try/catch)
通信は失敗する前提で、try/catchとステータス確認で備える。
通信は必ず失敗しうる
APIを叩く処理は、いつも成功するとは限りません。ネットワークが切れている、サーバーが落ちている、URLが間違っている、権限がない、といった理由で失敗します。失敗に備えていないと、アプリが突然止まったり、真っ白な画面になったりします。「失敗する前提で書く」のがプロの基本です。
fetch はステータスエラーで例外を投げない
重要な落とし穴です。fetch は 404 や 500 のようなエラー応答が返っても「通信自体は成功した」とみなし、例外を投げません。res.ok(または res.status)を自分で確認しないと、エラー応答を正常なデータとして扱ってしまいます。
try/catchで失敗を受け止める
try/catch は「try のブロックで問題が起きたら catch に飛ぶ」という仕組みです。await した処理が失敗(Promiseが失敗)すると catch に入るので、そこでエラー時の処理を書きます。あわせて res.ok を確認して、ステータスエラーも自分で例外に変えます。
interface User {
id: number;
name: string;
}
async function loadUser(): Promise<User | null> {
try {
const res = await fetch("https://api.example.com/user");
// 404 や 500 は自分で弾く
if (!res.ok) {
throw new Error("取得に失敗しました: " + res.status);
}
const user = (await res.json()) as User;
return user;
} catch (error) {
// ネットワーク切れやステータスエラーがここに来る
console.error(error);
return null; // 失敗時は null を返す設計にする
}
}なぜ戻り値の型を User | null にするのか
失敗時は null を返す設計にすると、戻り値の型が で User | null になります。呼び出し側は「null かもしれない」と型で知らされるので、必ず失敗のケースを考えて書くことになります。型が成功と失敗の両方を語ってくれるわけです。
備えなし
// 失敗を考えていない
const res = await fetch(url);
const user = await res.json();
// 通信失敗やエラー応答でそのまま壊れる
return user;備えあり
try {
const res = await fetch(url);
if (!res.ok) throw new Error(String(res.status));
return (await res.json()) as User;
} catch (e) {
console.error(e);
return null;
}AIにはこう聞く
「このfetch処理に、res.okのチェックとtry/catchを足して、失敗時はnullを返す形にして」と頼むと、抜けがちなエラーハンドリングを補ってもらえます。生成後は「res.okのチェックが入っているか」「catchで握りつぶしていないか」を自分の目で確認しましょう。
- 通信は必ず失敗しうるので、失敗前提で書く
- fetch は 404/500 で例外を投げない → res.ok を自分で確認
- try/catch で失敗を受け止める
- 失敗時は null を返すなど、型(User | null)で呼び出し側に伝える
読んでも腑に落ちない所は、AIに噛み砕いてもらいましょう。
理解度チェック
答えられれば、面接で説明できる状態に一歩近づきます。
fetchで404が返ってきたとき、標準の挙動として正しいものは?
失敗時にnullを返す設計にしたとき、戻り値の型として自然なものは?
fetchを使う処理で、なぜres.okの確認とtry/catchの両方が必要なのか説明してください。
記述式です。まず自分の言葉で答えを考えてから、模範解答を開いて自己採点してください。