【JavaScript】非同期処理とTryCatch
こんにちは、葛の葉です。
JavaScriptにおける非同期処理とtry catch文についてみてみましょう。一般的に、try
文内で発生したErrorはcatch
文に移動します。
try { throw new Error('Test Error'); console.log('hogehoge'); } catch (error) { console.log('piyopiyo'); } // piyopiyo
そのエラーを検知したとき、catch
文にジャンプします。ご多分の通り、throw
を使うことでエラーを発生することが出来ます。すなわち、try文内において、throw文以下の命令は絶対に呼び出されることはありません。VSCodeにおいても3行目であるconsole.log('hogehoge')
は到達できないと表示されます。
では以下のような非同期処理においてはどうでしょうか。
try{ setTimeout(() => { throw new Error('hoge'); }, 5 * 100); } catch (e) { console.log('piyopiyo'); } /* /home/~~~/a.js:3 throw new Error('hoge'); ^ Error: hoge */
このように、非同期処理中に発生したエラーについてはcatchできません。
そもそもJavaScriptにはコールスタックが働いて、エラー発生時において、関数の呼び出した元の関数まで遡っていくことができます。その遡り内にtry catchがあれば、そこでエラーを検知することが出来ます。非同期処理内において発生したエラーにおいても同様にコールスタックにてエラーが遡ることになるのですが、Javascript特有のイベントループにて、非同期処理を実行する環境は各イベントのフェーズがGlobalとなるため、普段書いている同期処理内のtrycatchに引っかかることがありません。
下記のようにasyncとawaitをPromiseと組み合わせることで同期処理内にてcatchすることが出来ます。
const promise = new Promise((resolve, reject)=>{ const hoge = 'hogehoge'; try{ throw new Error('ERROR DESU'); resolve(hoge); }catch(e){ reject(e); } }); (async() =>{ try{ await promise.then(); } catch (e) { console.log('piyopiyo'); } })(); // piyopiyo
イマイチこのあたりが完全に理解しきれていないので、今後きちんと勉強したいです。