JavaScriptでエラーが起きてもプログラムを止めずに処理を続けるには、try-catch 文を使います。エラーを捕捉(catch)して対処することで、アプリケーションの安定性を高められます。
この記事では、基本構文から、throw で自分でエラーを出す方法、async/awaitでのエラー処理、そしてtry-catchで捕まえられないエラーまで解説します。
try { 処理 } catch (error) { 対処 } finally { 後処理 } が基本形です。エラー内容は error.message / error.name で取得します。async/awaitも同じ try-catch で扱え、自分でエラーを出すには throw new Error("...") を使います。基本構文(try / catch / finally)
エラーが起きる可能性のあるコードを try に書き、エラー時の処理を catch に書きます。finally はエラーの有無に関わらず必ず実行される後処理です(省略可)。
try {
const data = JSON.parse(text); // エラーが起きる可能性のある処理
console.log(data);
} catch (error) {
console.error("エラー:", error.message); // エラー時の処理
} finally {
console.log("終了処理"); // 成否に関わらず必ず実行
}
エラーオブジェクトが不要なら、引数を省いて catch { ... } とも書けます(ES2019以降)。リソース解放やローディング非表示など、確実に行いたい後処理は finally に置きます。
自分でエラーを投げる(throw)
想定外の値が来たときなど、自分でエラーを発生させたいときは throw を使います。throw new Error("メッセージ") が基本です。
function divide(a, b) {
if (b === 0) {
throw new Error("0で割ることはできません");
}
return a / b;
}
try {
divide(10, 0);
} catch (error) {
console.error(error.message); // "0で割ることはできません"
}
エラーの種類を見分ける(instanceof)
エラーには種類があり、error.name で名前を、instanceof で型を判別できます。組み込みの型には TypeError・SyntaxError・RangeError・ReferenceError などがあります。
try {
null.foo; // TypeError が発生
} catch (error) {
console.log(error.name); // "TypeError"
console.log(error.message);
if (error instanceof TypeError) {
console.log("型に関するエラー");
} else if (error instanceof SyntaxError) {
console.log("構文エラー");
}
}
たとえば JSON.parse() は不正な文字列で SyntaxError を投げます。JSONの読み込みとエラー処理はJSONファイルの読み込み方も参考になります。
async/awaitでのエラー処理
現代のJavaScriptで最もよく使うのが、async関数内の try-catchです。await したPromiseがrejectされると、その例外を catch で捕捉できます。Promiseチェーンの .catch() より読みやすいのが利点です。
async function loadData(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`); // 失敗を自分でthrow
}
return await response.json();
} catch (error) {
console.error("読み込み失敗:", error.message);
} finally {
console.log("通信完了");
}
}
async/await の基本はPromiseとasync/awaitの使い方、fetch の通信はfetch APIで非同期通信を行うで詳しく解説しています。
try-catchで捕まえられないエラーに注意
try-catch は同期的に実行される範囲のエラーしか捕捉できません。次のような別タイミングで実行されるエラーは捕まえられないので注意してください。
// NG: setTimeout のコールバック内のエラーは外のcatchで捕まえられない
try {
setTimeout(() => {
throw new Error("捕捉されない");
}, 1000);
} catch (error) {
// ここには来ない(別タスクで実行されるため)
}
// NG: await しない Promise のエラーも捕捉できない
try {
fetch("/data"); // await が無い
} catch (error) {
// rejectされてもここには来ない
}
setTimeout などコールバック内のエラーは、そのコールバックの中で try-catch します。Promiseは await するか .catch() を付けることで捕捉できます。「同期的に実行される所だけ捕まえられる」と覚えておきましょう。よくある質問(FAQ)
JSON.parse・fetch・外部API呼び出しなど)の周囲に使います。一方、値が undefined かどうかなど事前に確認できるものは、try-catchより条件チェック(if)の方が適切な場合もあります。try・catch どちらが実行されても確実に実行されます。try-catch-finally をそのまま使えます。await でrejectされたPromiseは catch で捕捉できます。Promiseチェーンの .catch() より可読性が高く推奨されます。setTimeout のコールバックは後で別タスクとして実行されるため、外側の try-catch(すでに実行が終わっている)では捕捉できません。コールバックの中で try-catch してください。まとめ
try-catch は、try で処理、catch でエラー対処、finally で必ず行う後処理、というのが基本です。エラー内容は error.message / error.name、種類は instanceof で判別できます。
自分でエラーを出すなら throw new Error()、async/awaitのエラーも同じ try-catch で扱えます。ただし setTimeout 内や await しないPromiseのエラーは外のtry-catchでは捕まえられない点に注意しましょう。
