JavaScriptのtry/catchをわかりやすく解説!

GAS

はじめに

プログラミングにおいて避けられないのがエラー処理です。特にユーザー入力やネットワーク通信など、外部要因に依存する処理では予期せぬエラーが発生しがちです。JavaScriptではtry/catch構文を使うことで、エラーが発生してもプログラムが停止することなく、適切に対処することができます

この記事では、JavaScriptの例外処理の基本から実践的な使い方まで詳しく解説します。

try/catchの基本構文

try/catchの基本的な構文は以下のとおりです:

try {
  // エラーが発生する可能性のあるコード
} catch (error) {
  // エラーが発生した場合の処理
} finally {
  // エラーの有無にかかわらず必ず実行される処理(省略可能)
}

なぜtry/catchを使うのか?

try/catchを使う主な理由は:

  1. プログラムの継続性を保つ – エラーでプログラム全体が停止するのを防ぐ
  2. エラー情報の取得 – 何が問題だったのかを詳細に知ることができる
  3. ユーザーフレンドリーなエラー処理 – 技術的なエラーメッセージではなく、ユーザーに分かりやすいメッセージを表示できる
  4. 代替処理の実行 – エラー発生時に別の処理を試すことができる

簡単な例:0除算の処理

数値計算でよくあるエラーとして0による除算があります。以下の例では、ユーザーが入力した値で割り算を行う際に発生しうるエラーを処理しています:

function divide(a, b) {
  try {
    if (b === 0) {
      throw new Error("0で割ることはできません");
    }
    
    const result = a / b;
    console.log(`計算結果: ${result}`);
    return result;
  } catch (error) {
    console.error(`計算エラー: ${error.message}`);
    return null;
  }
}

// テスト
console.log(divide(10, 2));  // 計算結果: 5 → 5
console.log(divide(10, 0));  // 計算エラー: 0で割ることはできません → null

throwステートメントでエラーを発生させる

throwを使うと、任意のタイミングで意図的にエラーを発生させることができます:

function validateAge(age) {
  try {
    if (typeof age !== 'number') {
      throw new TypeError("年齢は数値で入力してください");
    }
    
    if (age < 0) {
      throw new RangeError("年齢は0以上の値にしてください");
    }
    
    if (age > 120) {
      throw new RangeError("年齢の値が大きすぎます");
    }
    
    console.log(`入力された年齢は ${age} 歳です`);
  } catch (error) {
    if (error instanceof TypeError) {
      console.error("型エラー:", error.message);
    } else if (error instanceof RangeError) {
      console.error("範囲エラー:", error.message);
    } else {
      console.error("予期せぬエラー:", error.message);
    }
  }
}

validateAge(25);    // 入力された年齢は 25 歳です
validateAge("30");  // 型エラー: 年齢は数値で入力してください
validateAge(-5);    // 範囲エラー: 年齢は0以上の値にしてください

エラーオブジェクトの種類

JavaScriptには様々な組み込みエラークラスがあります:

エラーオブジェクト説明
Error一般的なエラー
SyntaxError構文エラー
ReferenceError存在しない変数を参照した場合
TypeError値が期待される型ではない場合
RangeError数値が許容範囲外の場合
URIErrorURIの不正な使用
EvalErroreval()関数の使用に関するエラー

これらを使い分けることで、より具体的なエラー処理が可能になります。

非同期処理とtry/catch

Promiseでのエラー処理

Promiseベースの非同期処理では、.catch()メソッドを使ってエラーを捕捉できます:

function fetchData(url) {
  return fetch(url)
    .then(response => {
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      return response.json();
    })
    .then(data => {
      console.log("データの取得に成功:", data);
      return data;
    })
    .catch(error => {
      console.error("データの取得に失敗:", error.message);
      return null;
    });
}

fetchData('https://api.example.com/data');

Promiseでのエラー処理は、「約束が果たせなかった時の対応策」と考えるとわかりやすいでしょう。

JavaScriptのPromiseは「この処理を後でやるね」という約束ですが、その処理が失敗することもあります。例えば、ネットワークエラーやサーバーエラーなどです。

.catch()メソッドは、そんな「約束が果たせなかった時」に実行される特別な処理です。約束(Promise)が失敗した時、自動的に.catch()の中の処理が実行されます。

async/awaitでのtry/catch

async/await構文を使う場合は、通常のtry/catchでエラーを処理できます:

async function fetchUserData(userId) {
  try {
    const response = await fetch(`https://api.example.com/users/${userId}`);
    
    if (!response.ok) {
      throw new Error(`ユーザーデータの取得に失敗しました。ステータス: ${response.status}`);
    }
    
    const userData = await response.json();
    console.log("ユーザーデータ:", userData);
    return userData;
  } catch (error) {
    console.error("エラーが発生しました:", error.message);
    
    // エラータイプに応じた処理
    if (error instanceof TypeError) {
      console.error("ネットワークエラーの可能性があります。インターネット接続を確認してください。");
    }
    
    return null;
  } finally {
    console.log("処理が完了しました(成功/失敗に関わらず)");
  }
}

// 使用例
async function displayUserProfile(userId) {
  const userData = await fetchUserData(userId);
  
  if (userData) {
    // ユーザーデータを表示する処理
    document.getElementById('username').textContent = userData.name;
  } else {
    // エラー時の代替表示
    document.getElementById('user-profile').innerHTML = '<p>ユーザー情報を読み込めませんでした</p>';
  }
}

async/awaitは、Promiseをより読みやすく書くための方法ですが、エラー処理は通常のtry/catchを使います。これは普通のJavaScriptのコードと同じような書き方ができるので、とても直感的です。

async/awaitでのエラー処理は、「料理のレシピ」と考えるとイメージしやすいでしょう

実践的なユースケース(例を載せてみました)

JSONパースのエラー処理

不正なJSONデータを処理する場合:

function parseUserData(jsonString) {
  try {
    const userData = JSON.parse(jsonString);
    return userData;
  } catch (error) {
    console.error("JSONの解析に失敗しました:", error.message);
    return { error: true, message: "データの形式が不正です" };
  }
}

// 正常なJSONの場合
const validJSON = '{"name": "鈴木太郎", "age": 28}';
console.log(parseUserData(validJSON));  // {name: "鈴木太郎", age: 28}

// 不正なJSONの場合
const invalidJSON = '{"name": "鈴木太郎", age: 28}';  // age周りのクォートが抜けている
console.log(parseUserData(invalidJSON));  // {error: true, message: "データの形式が不正です"}

ローカルストレージのアクセスエラー処理

ブラウザのローカルストレージへのアクセスでエラーが発生する場合:

function saveToLocalStorage(key, data) {
  try {
    localStorage.setItem(key, JSON.stringify(data));
    return true;
  } catch (error) {
    // QuotaExceededErrorなど、ストレージ容量の問題
    if (error instanceof DOMException) {
      console.error("ストレージへの保存に失敗しました:", error.message);
      alert("保存できる容量を超えました。他のデータを削除してください。");
    } else {
      console.error("予期せぬエラー:", error.message);
    }
    return false;
  }
}

function getFromLocalStorage(key, defaultValue = null) {
  try {
    const item = localStorage.getItem(key);
    return item ? JSON.parse(item) : defaultValue;
  } catch (error) {
    console.error("データの取得に失敗しました:", error.message);
    return defaultValue;
  }
}

フォーム検証でのエラー処理

ユーザー入力の検証にtry/catchを活用する例:

function validateForm(formData) {
  try {
    // メールアドレスの検証
    const email = formData.get('email');
    if (!email) {
      throw new Error("メールアドレスは必須です");
    }
    
    if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
      throw new Error("メールアドレスの形式が不正です");
    }
    
    // パスワードの検証
    const password = formData.get('password');
    if (!password || password.length < 8) {
      throw new Error("パスワードは8文字以上必要です");
    }
    
    // 検証通過
    return { valid: true };
  } catch (error) {
    return { 
      valid: false, 
      field: error.field || 'unknown',
      message: error.message 
    };
  }
}

// 使用例
document.querySelector('form').addEventListener('submit', function(event) {
  event.preventDefault();
  const formData = new FormData(this);
  const result = validateForm(formData);
  
  if (result.valid) {
    // フォーム送信処理
    submitForm(formData);
  } else {
    // エラーメッセージを表示

だいぶ理解するのに時間がかかってしまうと思いますが少しずつJavascriptになれていきましょう。

コメント

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