JavaScriptの例外処理とエラーの書き方
JavaScriptの例外処理とエラーの書き方についてまとめました。
例外処理とエラーの書き方
例外処理(Exception Handling)とは、エラーが発生したときに飛ぶ特別な処理のことです。
try{}→catch{}→finally{} で処理されます。
try {
本来動かしたい処理を書く
throw new Error()
try の中の以下のコードは実行されず、
catch()に移行する
} catch(e) {
エラーの処理
} finally {
終了の処理
try でも catch でも実行される
}
例外処理のシンプルな例文
try {
console.log('start');
throw new Error(`エラーが発生しました`);
console.log('end');
} catch (e) {
console.log(e);
} finally {
console.log('終了');
}
//start
//Error: エラーが発生しました
//終了
try{}の中のthrow new Error()以下は実行されずに、catch{}に移行しているのがわかります。
実際は、throw new Error()は別の関数に記述することが多いです。
次のようなケースをみてみましょう。
例外処理の具体例
次のasync/awaitの例文に例外処理を記述してみます。
//userデータをとってくる
async function fetchData() {
const response = await fetch('users.json');
const json = await response.json();
return json;
}
//データを加工する
async function init() {
const users = await fetchData(); //ここでエラーが投げられる
for (const user of users) {
console.log(`私は${user.name}です。${user.age}才です。`);
}
}
// 実行する
init();
まず、上のようにデータを取得する処理とデータを加工する処理を分けます。
そして、データを取得するときにエラーがあった場合、加工する前にエラーメッセージを投げたいとします。
つまり、throw new Error()を記述するのは、データをとってくる処理のところになります。
エラーを出すために、たとえばjson.lengthが0のときにエラーを投げる処理とします。jsonファイルのデータを消すとcatch{}が反応します。
そして、try{}の部分で本来行いたい処理を記述します。
その中で、データを加工する前にエラーをエラーを投げられるようにします。(await fetchData();の部分)
//userデータをとってくる
async function fetchData() {
const response = await fetch('users.json');
if (response.ok) {
const json = await response.json();
if (!json.length) {
throw new Error('データがありません');
}
return json;
}
}
//データを加工する
async function init() {
try {
const users = await fetchData(); //ここでエラーが投げられる
for (const user of users) {
console.log(`私は${user.name}です。${user.age}才です。`);
}
} catch (e) {
console.log(e);
} finally {
console.log('終了します。');
}
}
// 実行する
init();
// データがありません
// 終了します。
そして、エラーが投げられたときに、catch{}に移行します。
このように、throw new Error()はエラーを投げるだけにすることで、エラーの処理はcatch{}内で書き分けることが可能になります。
Promiseをより直感的に記述できるasync/awaitに関しては次の記事を参考にしてみてください。
fetch()メソッドについては、次の記事を参考にしてみてください。
カスタムエラー
Errorというクラスを継承して、独自のエラー文を返すことができるようになります。
//userデータをとってくる
async function fetchData() {
const response = await fetch('users.json');
if (response.ok) {
const json = await response.json();
if (!json.length) {
throw new NoDataError('データがありません');
}
return json;
}
}
class NoDataError extends Error {
constructor(message) {
super(message);
this.name = 'NoDataError'; //nameを設定しないとそのままErrorがでる
}
}
// NoDataError: データがありません
nameを設定しないとそのまま’Error’がでてしまいます。(ex. Error: データがありません)
throwでエラーが投げられたとき、try{}catch{}でハンドリングしないとそれ移行の処理が行われないため、throwを使うときは必ず例外処理のハンドリングを行いましょう。
例外処理の中で条件分岐をする際に、このカスタムエラーが役に立ちます。
例外処理の中で条件分岐をするというのは、たとえばcatch{}の中で次のようにします。
//データを加工する
async function init() {
try {
const users = await fetchData(); //ここでエラーが投げられる
for (const user of users) {
console.log(`私は${user.name}です。${user.age}才です。`);
}
} catch (e) {
if (e instanceof NoDataError) {
console.log(e);
} else {
console.log('処理できませんでした。');
}
} finally {
console.log('終了します。');
}
}
// 実行する
init();
このようにすると、データがない場合は、「データがありません」、それ以外のエラーの場合は、「処理できませんでした。」とエラーのメッセージを分けることができます。