ここでは async/await と finally を組み合わせたときの制御の流れ、特にreturn や throw を使うとどうなるか、を 具体的な例で丁寧に 解説します。
目的
try / catch / finally は、async 関数でも使えます。
でも「finally の中で return したら?」とか「throw したら?」という挙動は少しトリッキーです。
① 基本形:finally は「必ず実行される」
async function fetchData() {
try {
console.log("①: API呼び出し開始");
const res = await fetch("https://example.com/data");
const data = await res.json();
console.log("②: データ取得成功");
return data;
} catch (err) {
console.error("③: エラー発生", err);
throw err; // 上位にエラーを再スロー
} finally {
console.log("④: 後処理(ローディング解除など)");
}
}
fetchData()
.then(() => console.log("⑤: 成功完了"))
.catch(() => console.log("⑥: エラー処理完了"));
JavaScript🧭 実行順(成功時)
① → ② → ④ → ⑤
🧭 実行順(失敗時)
① → ③ → ④ → ⑥
✅ finally は「成功・失敗に関わらず」最後に必ず実行される。
② finally の中で return してしまった場合(⚠️落とし穴)
async function fetchData() {
try {
console.log("①: try中");
throw new Error("APIエラー");
} catch (err) {
console.log("②: catch中");
throw err;
} finally {
console.log("③: finally中");
return "④: finallyのreturn値";
}
}
fetchData()
.then(v => console.log("⑤:", v))
.catch(e => console.log("⑥:", e.message));
JavaScript🔍 実行結果:
①: try中
②: catch中
③: finally中
⑤: ④: finallyのreturn値
⚠️ catch の throw が無視され、finally の return が優先されます!
つまり:
finally内のreturnは、エラーも成功も上書きしてしまう。- 本来 throw すべき例外が握りつぶされてしまう。
🧠 避けるべき: finally 内で return しない。
③ finally の中で throw してしまった場合(上位に伝わる)
async function fetchData() {
try {
console.log("①: try中");
throw new Error("元のエラー");
} catch (err) {
console.log("②: catch中");
throw err;
} finally {
console.log("③: finally中");
throw new Error("finallyでの新しいエラー");
}
}
fetchData()
.then(() => console.log("⑤: 成功"))
.catch(e => console.log("⑥:", e.message));
JavaScript🧭 実行結果:
①: try中
②: catch中
③: finally中
⑥: finallyでの新しいエラー
👉 finally の throw が最終的に優先される。
💡つまり:
- finally で throw すると、catch のエラー内容を上書きしてしまう。
✅ 良いパターン(安全な finally の使い方)
async function fetchDataSafe() {
let connection;
try {
connection = await connectDB();
const result = await connection.query("SELECT * FROM users");
return result;
} catch (err) {
console.error("エラー:", err);
throw err; // エラーは上位に伝える
} finally {
if (connection) {
await connection.close(); // 必ず後処理
console.log("DB接続を閉じました");
}
}
}
JavaScript✅ finally の中では「後処理だけ」するのが原則
→ return や throw は避けるべき。
まとめ(初心者向けチェックポイント)
| ケース | finally の中で何をしたか | 結果 |
|---|---|---|
| return | エラーや元の戻り値を上書きしてしまう | ⚠️危険 |
| throw | 元のエラーを上書きしてしまう | ⚠️危険 |
| 後処理だけ(ログ、解放など) | 正しい使い方 | ✅安全 |
まとめの一言:
finallyの目的は「後片付け」。
値を返したり、新しいエラーを投げたりしないようにしましょう。


