ここでは、「fetch × async/await × finally」 を組み合わせて、
「通信成功・失敗どちらでも後処理を確実に実行する」コードを、
初心者でも理解できるようにステップごとに解説します。
ゴール
✅ 非同期処理での
try...catch...finallyの流れを理解する
✅ 通信が成功しても失敗しても「後片付け(finally)」が必ず動くことを確認する
基本構造(復習)
try {
// ① 通常の処理
} catch (err) {
// ② エラーが起きたときに実行される
} finally {
// ③ 成功しても失敗しても必ず実行される(後処理)
}
実例1:fetch + async/await + finally
async function fetchUserData() {
console.log('--- 通信開始 ---');
try {
const response = await fetch('https://api.example.com/user/123');
if (!response.ok) {
throw new Error(`HTTPエラー: ${response.status}`);
}
const data = await response.json();
console.log('✅ データ取得成功:', data);
} catch (err) {
console.error('❌ エラー発生:', err.message);
} finally {
console.log('🧹 後処理: ローディング表示を消す、接続を閉じるなど');
}
console.log('--- 通信終了 ---');
}
fetchUserData();
JavaScript実行の流れ
✅ 通信成功時
--- 通信開始 ---
✅ データ取得成功: { ... }
🧹 後処理: ローディング表示を消す、接続を閉じるなど
--- 通信終了 ---
❌ 通信失敗時(例: URLが間違い)
--- 通信開始 ---
❌ エラー発生: Failed to fetch
🧹 後処理: ローディング表示を消す、接続を閉じるなど
--- 通信終了 ---
👉 成功でも失敗でも finally は必ず実行される。
実務的な応用(UI付きシミュレーション)
たとえば「通信中はローディング表示、終わったら消す」というような処理。
async function loadData() {
const loader = document.querySelector('#loader');
loader.style.display = 'block'; // ローディング表示ON
try {
const response = await fetch('https://api.example.com/data');
if (!response.ok) throw new Error('サーバーエラー');
const result = await response.json();
console.log('データ取得:', result);
} catch (err) {
console.error('通信エラー:', err.message);
} finally {
loader.style.display = 'none'; // 成否に関係なく非表示
console.log('ローディング終了');
}
}
JavaScript💬 解説:
- 通信成功 → データを使う
- 通信失敗 → エラーメッセージ表示
- finally → 「ローディング中」UIをOFFにする
(成功しても失敗しても“後片付け”は必ず必要)
補足:return や throw があっても finally は動く
async function testFinally() {
try {
console.log('try内');
return 'done';
} finally {
console.log('finallyは必ず実行される');
}
}
testFinally();
JavaScript出力:
try内
finallyは必ず実行される
✅ return の前でも finally は必ず動く!
🚫 悪い例:finally を忘れてリソースを放置
async function badExample() {
const conn = openDatabaseConnection();
const data = await fetchData(conn); // ← ここでエラーになることも
conn.close(); // ← エラーが起きると実行されない!
}
JavaScript→ 途中で例外が出ると conn.close() が呼ばれず、「接続が閉じられない」などのバグに。
✅ 良い例:finally で安全に後処理
async function goodExample() {
const conn = openDatabaseConnection();
try {
const data = await fetchData(conn);
console.log('取得:', data);
} catch (e) {
console.error('失敗:', e.message);
} finally {
conn.close(); // ← 必ず実行される
}
}
JavaScript練習問題
問題1:
次のコードは「ローディング中」を消し忘れています。finally を使って直してください。
async function getData() {
showLoading(); // ローディング表示
const response = await fetch('https://wrong.url');
const data = await response.json();
hideLoading(); // ← 通信エラー時に実行されない!
}
JavaScript解答例:
async function getData() {
showLoading();
try {
const response = await fetch('https://wrong.url');
const data = await response.json();
console.log('成功:', data);
} catch (e) {
console.error('失敗:', e.message);
} finally {
hideLoading(); // ← 成否関係なく必ず実行
}
}
JavaScriptまとめ:finally の使いどころ
| 状況 | finally の使い道 |
|---|---|
| ローディング表示を消す | UI の後片付け |
| ファイルを閉じる | リソース解放 |
| データベース接続を切る | サーバー側の安定運用 |
| 一時変数やフラグのリセット | 状態を元に戻す |
まとめ(ポイント整理)
finallyは 成功・失敗・return の有無に関係なく必ず実行される。fetchのような非同期処理では「UIの後片付け」や「接続の終了」に最適。- 例外が起きても「後始末」が安全にできるように、try/catch/finally は3点セットで使うのがベスト。


