JavaScript | finally と async/await の中で return や throw を組み合わせた高度な制御

JavaScript JavaScript
スポンサーリンク

ここでは async/awaitfinally を組み合わせたときの制御の流れ、特に
returnthrow を使うとどうなるか、を 具体的な例で丁寧に 解説します。


目的

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 の中では「後処理だけ」するのが原則
returnthrow は避けるべき。


まとめ(初心者向けチェックポイント)

ケースfinally の中で何をしたか結果
returnエラーや元の戻り値を上書きしてしまう⚠️危険
throw元のエラーを上書きしてしまう⚠️危険
後処理だけ(ログ、解放など)正しい使い方✅安全

まとめの一言:

finally の目的は「後片付け」。
値を返したり、新しいエラーを投げたりしないようにしましょう。

タイトルとURLをコピーしました