はじめに
プログラミングにおいて避けられないのがエラー処理です。特にユーザー入力やネットワーク通信など、外部要因に依存する処理では予期せぬエラーが発生しがちです。JavaScriptではtry/catch
構文を使うことで、エラーが発生してもプログラムが停止することなく、適切に対処することができます。
この記事では、JavaScriptの例外処理の基本から実践的な使い方まで詳しく解説します。
try/catchの基本構文
try/catch
の基本的な構文は以下のとおりです:
try {
// エラーが発生する可能性のあるコード
} catch (error) {
// エラーが発生した場合の処理
} finally {
// エラーの有無にかかわらず必ず実行される処理(省略可能)
}
なぜtry/catchを使うのか?
try/catchを使う主な理由は:
- プログラムの継続性を保つ – エラーでプログラム全体が停止するのを防ぐ
- エラー情報の取得 – 何が問題だったのかを詳細に知ることができる
- ユーザーフレンドリーなエラー処理 – 技術的なエラーメッセージではなく、ユーザーに分かりやすいメッセージを表示できる
- 代替処理の実行 – エラー発生時に別の処理を試すことができる
簡単な例: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 | 数値が許容範囲外の場合 |
URIError | URIの不正な使用 |
EvalError | eval()関数の使用に関するエラー |
これらを使い分けることで、より具体的なエラー処理が可能になります。
非同期処理と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になれていきましょう。
コメント