基礎から学ぶJavaScript入門 90日コース | JavaScriptでデータを扱う - Day 26:try / catch

90日で身につけるJavaScript
スポンサーリンク
スポンサーリンク
  1. Day 26:try / catch(前半)
  2. 例外処理とは何か
    1. 「予期しないエラーを“受け止める”ための仕組み」
  3. try / catch / finally の基本構造
    1. try:エラーが起きるかもしれない処理を書く場所
    2. catch:エラーが発生したときに実行される場所
    3. finally:成功・失敗に関わらず最後に必ず実行される場所
  4. JSON変換時のエラー処理を考える
    1. なぜJSONまわりで例外処理が必要なのか
  5. ステップバイステップ:JSON.parse() を try / catch で安全にする
    1. ステップ1:危険な処理を try ブロックに入れる
    2. ステップ2:エラー内容をログに残す
    3. ステップ3:安全な関数としてまとめる
  6. finally を JSON処理でどう使うか
    1. 「後片付け」や「ログ」を必ず実行したいとき
  7. Day 26 前半 練習テンプレート(ブラウザで実行可能)
  8. Day 26 前半のまとめ
  9. Day 26:try / catch(後半)
  10. どこに try / catch を書くべきかを考える
    1. 「落ちる可能性があるところだけ」を狙って守る
    2. 「危険な処理」を小さく囲む
  11. JSON変換時のエラー処理を“パターン化”する
    1. パターン1:安全なJSONパース関数を作る
    2. パターン2:JSON.stringify() の失敗も考慮する
  12. finally を「後片付け」として意識する
    1. 例:ローディング表示のON/OFFを必ず行う
  13. セキュリティの視点から見る JSONエラー処理
    1. エラーメッセージをそのままユーザーに見せない
  14. Day 26 後半 練習テンプレート(ブラウザで実行可能)
  15. Day 26 後半のまとめ

Day 26:try / catch(前半)

「エラーが起きても“アプリを落とさずに”安全に処理するための仕組み」

Day 26では、JavaScriptでエラーを安全に扱うための仕組みである 例外処理(try / catch / finally) を学びます。 ここまでで「エラーの種類」や「コンソールで原因を特定する」ことは学んできましたが、今回は一歩進んで、

エラーが起きても、アプリ全体を止めずに“うまく受け止める”コードを書く

という考え方を身につけていきます。

例外処理とは何か

「予期しないエラーを“受け止める”ための仕組み」

例外処理とは、

実行中に起きたエラー(例外)をキャッチして、 アプリがクラッシュしないようにする仕組み

のことです。

通常、JavaScriptでエラーが発生すると、その場で処理が止まり、 それ以降のコードは実行されません。

console.log('処理開始');

JSON.parse('これはJSONではありません'); // ここでエラー

console.log('ここには到達しません'); // 実行されない
JavaScript

しかし、例外処理を使うと、

  • エラーが起きても、アプリ全体は落ちない
  • エラー内容をログに残したり、ユーザーにメッセージを出したりできる
  • 「失敗したときの振る舞い」をコードで定義できる

ようになります。

try / catch / finally の基本構造

try:エラーが起きるかもしれない処理を書く場所

try ブロックには、

「エラーが起きるかもしれない処理」

を書きます。

try {
  // エラーが起きるかもしれない処理
  const result = JSON.parse('これはJSONではありません');
  console.log('パース結果:', result);
} catch (error) {
  // エラーが起きたときの処理
  console.log('JSONのパースに失敗しました');
}
JavaScript

catch:エラーが発生したときに実行される場所

catch ブロックには、

「エラーが発生したときに実行したい処理」

を書きます。

try {
  const result = JSON.parse('これはJSONではありません');
  console.log('パース結果:', result);
} catch (error) {
  console.log('JSONのパースに失敗しました');
  console.log('エラー内容:', error); // エラーオブジェクトを確認できます
}
JavaScript
  • error には、発生したエラーオブジェクトが渡されます。
  • これをログに残したり、画面に表示したりできます。

finally:成功・失敗に関わらず最後に必ず実行される場所

finally ブロックには、

「成功しても失敗しても、最後に必ず実行したい処理」

を書きます。

try {
  const result = JSON.parse('{"id":101,"name":"佐藤"}'); // 正しいJSON
  console.log('パース成功:', result);
} catch (error) {
  console.log('パース失敗:', error);
} finally {
  console.log('このメッセージは必ず実行されます');
}
JavaScript
  • try が成功しても、catch が実行されても、 finally は必ず実行されます。
  • 「後片付け」や「ログ出力」などに使われます。

JSON変換時のエラー処理を考える

なぜJSONまわりで例外処理が必要なのか

JSON.parse() は、

「渡された文字列が正しいJSON形式であること」

を前提にしています。

もし、壊れたJSONや意図しない文字列を渡すと、 JSON.parse() はエラーを投げます。

const badJson = '{id:101,name:"佐藤"}'; // 不正なJSON

const obj = JSON.parse(badJson); // ここでエラー
console.log(obj); // 実行されない
JavaScript

このままだと、アプリ全体が止まってしまう可能性があります。 そこで、try / catch を使って「安全にパースする」コードを書きます。

ステップバイステップ:JSON.parse() を try / catch で安全にする

ステップ1:危険な処理を try ブロックに入れる

const jsonString = '{id:101,name:"佐藤"}'; // 不正なJSON

try {
  // エラーが起きるかもしれない処理
  const obj = JSON.parse(jsonString);
  console.log('パース成功:', obj);
} catch (error) {
  console.log('JSONのパースに失敗しました');
}
JavaScript
  • JSON.parse(jsonString) がエラーを投げても、 catch ブロックで受け止めることができます。
  • これにより、アプリ全体が止まることを防げます。

ステップ2:エラー内容をログに残す

const jsonString = '{id:101,name:"佐藤"}';

try {
  const obj = JSON.parse(jsonString);
  console.log('パース成功:', obj);
} catch (error) {
  console.log('JSONのパースに失敗しました');
  console.log('エラー内容:', error.message); // エラーメッセージだけ表示
}
JavaScript
  • error.message には、エラーの説明が入っています。
  • これをログに残すことで、後から原因を追いやすくなります。

ステップ3:安全な関数としてまとめる

JSON文字列を安全にパースする関数を作ってみます。

function safeJsonParse(jsonString) {
  try {
    const result = JSON.parse(jsonString);
    return {
      success: true,   // 成功したかどうか
      data: result,    // パース結果
      error: null,     // エラーはなし
    };
  } catch (error) {
    return {
      success: false,  // 失敗した
      data: null,      // データはなし
      error: error,    // エラーオブジェクトを返す
    };
  }
}

const goodJson = '{"id":101,"name":"佐藤"}';
const badJson = '{id:101,name:"佐藤"}';

const result1 = safeJsonParse(goodJson);
console.log('goodJsonの結果:', result1);

const result2 = safeJsonParse(badJson);
console.log('badJsonの結果:', result2);
JavaScript
  • 成功・失敗に関わらず、同じ形のオブジェクトを返すことで、 呼び出し側のコードが書きやすくなります。

finally を JSON処理でどう使うか

「後片付け」や「ログ」を必ず実行したいとき

例えば、JSONのパース処理の前後で、 「処理開始」「処理終了」を必ずログに残したいとします。

function parseWithLog(jsonString) {
  console.log('JSONパース処理を開始します');

  try {
    const result = JSON.parse(jsonString);
    console.log('パース成功:', result);
    return result;
  } catch (error) {
    console.log('パース失敗:', error.message);
    return null;
  } finally {
    console.log('JSONパース処理を終了します'); // 成功・失敗に関わらず必ず実行
  }
}

parseWithLog('{"id":101,"name":"佐藤"}');      // 成功パターン
parseWithLog('{id:101,name:"佐藤"}');         // 失敗パターン
JavaScript
  • finally の中のログは、成功しても失敗しても必ず出力されます。
  • 「処理の開始と終了を必ず記録したい」といった場面で役立ちます。

Day 26 前半 練習テンプレート(ブラウザで実行可能)

以下のテンプレートをブラウザで開き、 コンソールで「try / catch / finally の動き」と「JSON変換時のエラー処理」を確認してください。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Day 26 前半:try / catch 練習テンプレート</title>
</head>
<body>
  <h1>Day 26 前半:try / catch / finally と JSONエラー処理</h1>
  <p>ブラウザのコンソールを開いて、ログを確認してください。</p>

  <script>
    console.log('--- 基本的な try / catch ---');

    try {
      console.log('tryブロックの処理を開始します');
      const result = JSON.parse('これはJSONではありません'); // 不正なJSON
      console.log('パース結果:', result); // ここには到達しません
    } catch (error) {
      console.log('catchブロックが実行されました');
      console.log('JSONのパースに失敗しました');
      console.log('エラー内容:', error.message);
    }

    console.log('--- try / catch / finally ---');

    try {
      console.log('tryブロック:正しいJSONをパースします');
      const result = JSON.parse('{"id":101,"name":"佐藤"}');
      console.log('パース成功:', result);
    } catch (error) {
      console.log('catchブロック:ここは今回は実行されません');
    } finally {
      console.log('finallyブロック:成功・失敗に関わらず必ず実行されます');
    }

    console.log('--- safeJsonParse関数のテスト ---');

    function safeJsonParse(jsonString) {
      try {
        const result = JSON.parse(jsonString);
        return {
          success: true,
          data: result,
          error: null,
        };
      } catch (error) {
        return {
          success: false,
          data: null,
          error: error,
        };
      }
    }

    const goodJson = '{"id":101,"name":"佐藤"}';
    const badJson = '{id:101,name:"佐藤"}';

    const result1 = safeJsonParse(goodJson);
    console.log('goodJsonの結果:', result1);

    const result2 = safeJsonParse(badJson);
    console.log('badJsonの結果:', result2);

    console.log('--- parseWithLog関数のテスト ---');

    function parseWithLog(jsonString) {
      console.log('JSONパース処理を開始します');

      try {
        const result = JSON.parse(jsonString);
        console.log('パース成功:', result);
        return result;
      } catch (error) {
        console.log('パース失敗:', error.message);
        return null;
      } finally {
        console.log('JSONパース処理を終了します');
      }
    }

    parseWithLog('{"id":101,"name":"佐藤"}');      // 成功パターン
    parseWithLog('{id:101,name:"佐藤"}');         // 失敗パターン

    console.log('--- Day 26 前半:try / catch の練習が完了しました ---');
  </script>
</body>
</html>

Day 26 前半のまとめ

Day 26前半では、

  • 例外処理が「エラーを受け止めて、アプリ全体を守るための仕組み」であること
  • try に「エラーが起きるかもしれない処理」を書き、 catch に「エラーが起きたときの処理」を書く基本構造
  • finally で「成功・失敗に関わらず必ず実行したい処理」を書けること
  • JSON.parse() のようにエラーを投げる可能性がある処理を、 try / catch で安全に包む考え方
  • 成功・失敗をわかりやすく返す safeJsonParse のような関数パターン

を確認しました。

例外処理は、 「エラーが起きても落ち着いて対処できるコードを書くための土台」 です。

Day 26後半では、さらに実践的なシナリオを通して、 「try / catch をどこに書くべきか」「どこまで例外処理で包むべきか」といった感覚も深めていきます。


Day 26:try / catch(後半)

「“落ちてもおかしくないところ”だけを守る、現実的な例外処理の書き方」

Day 26後半では、前半で学んだ

  • 例外処理
  • try
  • catch
  • finally

を、より実務に近い形で使っていきます。 特に JSON変換時のエラー処理 を軸に、

  • どこに try / catch を書くべきか
  • どこまで例外処理で包むべきか
  • エラーが起きたときに「どう振る舞うか」をコードで決める

という視点をステップバイステップで整理していきます。

どこに try / catch を書くべきかを考える

「落ちる可能性があるところだけ」を狙って守る

例外処理は、なんでもかんでも try / catch で包めばいいわけではありません。 ポイントは、

「エラーが起きる可能性が高いところだけ」を狙って try / catch を書く

ことです。

JSONまわりで言えば、

  • JSON.parse()(文字列 → オブジェクト)
  • 場合によっては JSON.stringify()(オブジェクト → 文字列)

が「落ちる可能性がある処理」です。

// こういう書き方はあまりよくありません(範囲が広すぎる)
try {
  // いろいろな処理
  const jsonString = getJsonFromServer();
  const data = JSON.parse(jsonString);
  render(data);
  updateUI();
  saveLog();
} catch (error) {
  console.log('何かエラーが起きました', error);
}
JavaScript

これだと、

  • どこでエラーが起きたのかがわかりにくい
  • 「JSONパースの失敗」と「UI更新の失敗」が同じ扱いになってしまう

という問題があります。

「危険な処理」を小さく囲む

よりよい書き方は、

「落ちる可能性がある処理」を小さく囲む

ことです。

const jsonString = getJsonFromServer();

let data;

try {
  // JSON.parseだけを例外処理で守る
  data = JSON.parse(jsonString);
} catch (error) {
  console.error('JSONのパースに失敗しました', error);
  // ここで適切な代替処理を決める
  data = null;
}

// ここから先は「dataがnullかもしれない」という前提で書く
if (data === null) {
  showErrorMessage('データの読み込みに失敗しました。時間をおいて再度お試しください。');
} else {
  render(data);
}
JavaScript
  • 「どこで何が失敗したか」が明確になります。
  • 失敗したときの振る舞い(エラーメッセージを出すなど)も、 その場で決めることができます。

JSON変換時のエラー処理を“パターン化”する

パターン1:安全なJSONパース関数を作る

前半で作った safeJsonParse を、もう少し実務寄りに整理してみます。

function safeJsonParse(jsonString) {
  try {
    const result = JSON.parse(jsonString);

    return {
      success: true,      // 成功したかどうか
      data: result,       // パース結果
      errorMessage: null, // エラーメッセージはなし
    };
  } catch (error) {
    return {
      success: false,
      data: null,
      errorMessage: error.message, // エラーメッセージだけを返す
    };
  }
}
JavaScript

この関数を使うと、呼び出し側のコードがシンプルになります。

const responseText = '{id:101,name:"佐藤"}'; // 不正なJSON

const result = safeJsonParse(responseText);

if (!result.success) {
  console.log('JSONのパースに失敗しました:', result.errorMessage);
  showErrorMessage('データの読み込みに失敗しました。');
} else {
  console.log('パース成功:', result.data);
  render(result.data);
}
JavaScript
  • 成功・失敗を「フラグ」で判定できるので、 if文で分岐しやすくなります。
  • エラーメッセージだけを取り出してログや画面表示に使えます。

パターン2:JSON.stringify() の失敗も考慮する

JSON.stringify() は、基本的には安全ですが、 循環参照(オブジェクトが自分自身を参照しているなど)があるとエラーになります。

const obj = {};
obj.self = obj; // 自分自身を参照している

JSON.stringify(obj); // ここでエラー
JavaScript

これも try / catch で守ることができます。

function safeJsonStringify(value) {
  try {
    const json = JSON.stringify(value);
    return {
      success: true,
      json,
      errorMessage: null,
    };
  } catch (error) {
    return {
      success: false,
      json: null,
      errorMessage: error.message,
    };
  }
}

const obj = {};
obj.self = obj;

const result = safeJsonStringify(obj);

if (!result.success) {
  console.error('JSON.stringifyに失敗しました:', result.errorMessage);
} else {
  console.log('JSON文字列:', result.json);
}
JavaScript
  • 「保存や送信の前に、JSON.stringifyが失敗するかもしれない」という前提で、 安全なラッパー関数を用意しておくと安心です。

finally を「後片付け」として意識する

例:ローディング表示のON/OFFを必ず行う

JSONを使った通信では、 「読み込み中」のインジケーター(ローディング表示)を出すことがあります。

function fetchAndRender(jsonString) {
  showLoading(); // ローディング表示ON

  try {
    const data = JSON.parse(jsonString);
    render(data); // 画面に表示
  } catch (error) {
    console.error('JSONのパースに失敗しました:', error.message);
    showErrorMessage('データの読み込みに失敗しました。');
  } finally {
    hideLoading(); // ローディング表示OFF(成功・失敗に関わらず必ず実行)
  }
}
JavaScript
  • showLoading()hideLoading()try / catch / finally の前後に置くことで、 「どんな結果でも最後にローディングを消す」ことが保証されます。
  • これが「後片付け」としての finally の典型的な使い方です。

セキュリティの視点から見る JSONエラー処理

エラーメッセージをそのままユーザーに見せない

error.message には、内部的な情報が含まれることがあります。 それをそのままユーザーに表示するのは、セキュリティ的に好ましくありません。

try {
  const data = JSON.parse(jsonString);
  render(data);
} catch (error) {
  // これはあまりよくない例(内部情報をそのまま見せてしまう)
  alert('エラーが発生しました:' + error.message);
}
JavaScript

よりよい書き方は、

  • ユーザーには「一般的なメッセージ」を見せる
  • 詳細なエラー内容はコンソールやログに残す

という分け方です。

try {
  const data = JSON.parse(jsonString);
  render(data);
} catch (error) {
  console.error('JSONパースエラー:', error.message); // 開発者向けログ
  showErrorMessage('データの読み込みに失敗しました。時間をおいて再度お試しください。'); // ユーザー向けメッセージ
}
JavaScript
  • こうすることで、ユーザーには余計な内部情報を見せずに済みます。
  • 開発者はコンソールやログから詳細な原因を追うことができます。

Day 26 後半 練習テンプレート(ブラウザで実行可能)

以下のテンプレートをブラウザで開き、 コンソールを見ながら「JSON変換時のエラー処理」と「try / catch / finally の使い分け」を確認してください。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Day 26 後半:try / catch と JSONエラー処理 練習テンプレート</title>
</head>
<body>
  <h1>Day 26 後半:JSON変換時のエラー処理(安全なパターンを身につける)</h1>
  <p>ブラウザのコンソールを開いて、ログを確認してください。</p>

  <script>
    console.log('--- safeJsonParseのテスト ---');

    function safeJsonParse(jsonString) {
      try {
        const result = JSON.parse(jsonString);
        return {
          success: true,
          data: result,
          errorMessage: null,
        };
      } catch (error) {
        return {
          success: false,
          data: null,
          errorMessage: error.message,
        };
      }
    }

    const goodJson = '{"id":101,"name":"佐藤"}';
    const badJson = '{id:101,name:"佐藤"}';

    const result1 = safeJsonParse(goodJson);
    console.log('goodJsonの結果:', result1);

    const result2 = safeJsonParse(badJson);
    console.log('badJsonの結果:', result2);

    console.log('--- safeJsonStringifyのテスト ---');

    function safeJsonStringify(value) {
      try {
        const json = JSON.stringify(value);
        return {
          success: true,
          json,
          errorMessage: null,
        };
      } catch (error) {
        return {
          success: false,
          json: null,
          errorMessage: error.message,
        };
      }
    }

    const obj = {};
    obj.self = obj; // 循環参照

    const stringifyResult = safeJsonStringify(obj);
    console.log('循環参照オブジェクトの結果:', stringifyResult);

    console.log('--- finallyでローディング表示を制御するイメージ ---');

    function showLoading() {
      console.log('ローディング表示:ON');
    }

    function hideLoading() {
      console.log('ローディング表示:OFF');
    }

    function showErrorMessage(message) {
      console.log('ユーザー向けエラーメッセージ:', message);
    }

    function render(data) {
      console.log('画面にデータを表示します:', data);
    }

    function fetchAndRender(jsonString) {
      showLoading();

      try {
        const data = JSON.parse(jsonString);
        render(data);
      } catch (error) {
        console.error('JSONパースエラー:', error.message);
        showErrorMessage('データの読み込みに失敗しました。時間をおいて再度お試しください。');
      } finally {
        hideLoading();
      }
    }

    console.log('--- 正しいJSONでfetchAndRenderを実行 ---');
    fetchAndRender('{"id":101,"name":"佐藤"}');

    console.log('--- 不正なJSONでfetchAndRenderを実行 ---');
    fetchAndRender('{id:101,name:"佐藤"}');

    console.log('--- Day 26 後半:try / catch とJSONエラー処理の練習が完了しました ---');
  </script>
</body>
</html>

Day 26 後半のまとめ

Day 26後半では、

  • 「どこに try / catch を書くべきか」を、JSON変換を例に考えたこと
  • JSON.parse()JSON.stringify() を安全に包む関数パターン(safeJsonParse / safeJsonStringify
  • finally を使って「ローディング表示のON/OFF」などの後片付けを必ず実行する書き方
  • セキュリティの観点から、「内部的なエラーメッセージをそのままユーザーに見せない」考え方

を確認しました。

例外処理は、 「エラーが起きても、アプリ全体を落とさずに、意味のある振る舞いを続けるための技術」 です。

JSONまわりのように「落ちてもおかしくないポイント」を意識して、 そこだけを丁寧に try / catch / finally で包んでいく感覚を、 ぜひコードを書きながら育てていってください。

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