JavaScriptを触っていて、同期・非同期関数のエラーハンドリングについて曖昧なまま理解していたのが、先日ようやく自分自身の中で納得できる説明ができたので、それを書き残しておきます。
同期・非同期について曖昧な方は過去記事をよんでみてね
エラーハンドリングとは?
プログラミング実行最中に、予期せぬエラーに遭遇することがあります。
そうなった場合、プログラムがそこで中断してしまうかもしれません。
ただし、エラーハンドリングをすることで、エラーが起きても中断せずに続行をさせることができます。
JavaScriptでのエラーハンドリング
try, catch構文を使います。
try {
const a = 1+1;
console.log(a);
} catch(err) {
console.log(err);
}
console.log("the world goes on");
このような感じで、エラーが起こる可能性のある処理をtry
の中に記述し、投げられたエラーをcatch
で獲得してくれ、そのあとの処理も続行してくれます。
例の中では、1+1の計算をしているだけですが、例えばサーバからデータをフェッチするときとか、もしかしたら失敗するかもしれない処理などをここに入れるのが正しいみたい。
同期関数のエラーハンドリングのやり方
さて、ここでややこしいのが同期と非同期のエラーハンドリングでした。全部try
の中に突っ込めばいいんじゃないの?と思ってたのですが、違いました。
同期関数の場合
同期しているということは、上から順番ずつプログラムが実行されます。
その場合は、上記で述べたようにtry, catch
を記述すればOKです。
const promiseFunction = () => new Promise((resolve, reject)=>{
setTimeout(() => {
reject('Throw error');
}, 300);
});
const main = async () => {
console.log("Before try, catch");
try {
await promiseFunction();
} catch(err) {
console.log(err);
}
console.log("After try, catch");
}
main();
Promiseは非同期オブジェクトになりますが、それをasync, await
で同期的に処理しています。その場合は上記で説明したtry, catch
で対応すれば大丈夫です。
こちらを実行すると以下が出力されます。
> Before try, catch
> Throw error
> After try, catch
試しにtry, catch
をなくしてみると以下の出力になります。
> Before try, catch
> [UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "Throw error".] {
code: 'ERR_UNHANDLED_REJECTION'
}
Before try, catchの後にすぐUnhandledPromiseRejection
を吐いてそこで実行が終わってしまいました。
非同期関数の場合
非同期しているということは、プログラムの作業が必ずしも上から下へと順番通りに実行されません。
そのため、try, catch
では非同期関数をしっかりとキャッチできないかもしれないのです。
なので、こういう書き方をします。
const promiseFunction = () => new Promise((resolve, reject)=>{
setTimeout(() => {
reject('Throw error');
}, 300);
});
const main = async () => {
console.log("Before try, catch");
promiseFunction().catch(err => console.log(err));
console.log("After try, catch");
}
main();
非同期関数にcatch
をチェーンしてしまいます。こうすることで、非同期にいつどこで実行されても必ずエラーをキャッチできます。
出力結果は以下です。
> Before try, catch
> After try, catch
> Throw error
まとめ
同期関数と非同期関数のエラーハンドリングについて、解説しました。
非同期の場合はどこで実行されるかわからないから、catchで紐づけてあげないとダメなんだなーと理解できました。
にほんブログ村に参加しております!よろしければクリックお願いします 🙂
にほんブログ村
コメント