ここは「複数の非同期処理(fetch など)をまとめて実行して、最後に共通の後処理をする」
という実務で非常に役立つテクニックです。
以下で、
- ❌ 悪い例(落とし穴あり)
- ✅ 良い例(安全で読みやすい制御)
を対比しながら、Promise.allとfinallyの組み合わせ方を解説します。
シナリオ
3つの API を並列で呼び出す:
/api/user
/api/posts
/api/comments
どれも時間がかかるが、「ローディング中スピナー」を出しておきたい。
→ すべて終わったらスピナーを消す(成功でも失敗でも)。
❌ 悪い例:finally を忘れて重複コードに
async function loadAllDataBad() {
showLoadingSpinner(); // ローディング表示
try {
const [user, posts, comments] = await Promise.all([
fetch("/api/user").then(res => res.json()),
fetch("/api/posts").then(res => res.json()),
fetch("/api/comments").then(res => res.json())
]);
console.log("すべて成功", { user, posts, comments });
} catch (err) {
console.error("どれか失敗しました", err);
}
// ← finally がないので、ここで後処理を書く必要がある
hideLoadingSpinner(); // 成功・失敗どちらでも呼ばれる保証がない
}
JavaScript問題点:
- 途中で例外が起きると、
hideLoadingSpinner()が呼ばれない可能性がある。 - つまり「ローディング中のまま止まる」バグが起きやすい。
✅ 良い例:finally で共通後処理を保証する
async function loadAllDataGood() {
showLoadingSpinner(); // ローディング表示開始
try {
const [user, posts, comments] = await Promise.all([
fetch("/api/user").then(res => res.json()),
fetch("/api/posts").then(res => res.json()),
fetch("/api/comments").then(res => res.json())
]);
console.log("✅ すべて成功", { user, posts, comments });
} catch (err) {
console.error("❌ どれか失敗しました:", err);
} finally {
hideLoadingSpinner(); // 成否に関わらず必ず実行!
console.log("🔁 ローディング終了");
}
}
loadAllDataGood();
JavaScript🧭 実行順:
showLoadingSpinner()
→ Promise.all(並列実行)
→ 成功 or 失敗
→ finally(hideLoadingSpinner)
✅ ポイント
Promise.allのどれか1つでも失敗すると 即 catch に飛ぶ。- でも finally は必ず実行されるので、「後処理(UI片付け)」が安全。
発展:部分成功を許容する(Promise.allSettled 版)
「どれか失敗しても、成功した分は使いたい」
というケースでは Promise.allSettled() が便利です。
async function loadAllDataSafe() {
showLoadingSpinner();
try {
const results = await Promise.allSettled([
fetch("/api/user").then(r => r.json()),
fetch("/api/posts").then(r => r.json()),
fetch("/api/comments").then(r => r.json())
]);
const user = results[0].status === "fulfilled" ? results[0].value : null;
const posts = results[1].status === "fulfilled" ? results[1].value : [];
const comments = results[2].status === "fulfilled" ? results[2].value : [];
console.log("部分結果", { user, posts, comments });
} finally {
hideLoadingSpinner();
console.log("UIを確実に片付けました");
}
}
JavaScriptこれで:
- どれか失敗してもエラーで止まらない
- finally で確実にローディング終了
statusを見て部分的に処理できる
まとめ
| 状況 | 推奨パターン | 理由 |
|---|---|---|
| 全部成功が前提 | Promise.all + finally | 簡潔・安全 |
| 一部失敗を許容 | Promise.allSettled + finally | 柔軟性が高い |
| UI 後処理が必要 | finally 内に記述 | 成否を問わず実行される |
コツの一言
finallyは「終わった後の片付け専用」。
並列処理の完了を待つにはPromise.all、
部分成功を扱うにはPromise.allSettled。


