【ITニュース解説】Smarter Error Handling in JavaScript: Group, Don’t Panic
2025年09月13日に「Dev.to」が公開したITニュース「Smarter Error Handling in JavaScript: Group, Don’t Panic」について初心者にもわかりやすく解説しています。
ITニュース概要
JavaScriptの`AggregateError`機能により、非同期処理やフォームバリデーションで同時に発生する複数のエラーを一つにまとめて扱える。これにより、エラー処理のコードが分かりやすくなり、ユーザーに正確な情報を提供しやすくなる。
ITニュース解説
JavaScriptでシステム開発を行う際、特に複数の処理が同時に進む「非同期処理」を扱う場面で、エラーの処理(エラーハンドリング)は非常に重要な要素となる。非同期処理とは、例えばウェブサイトからデータを取得する際のように、ある処理の完了を待たずに次の処理をすぐに開始するような動作を指す。この非同期処理が複雑になると、同時に複数のエラーが発生することがよくある。これまで、それぞれの失敗した処理が個別のエラーを発生させるため、それらを一つ一つ確認して対応するのは手間がかかり、コードも読みにくくなりがちだった。プログラムの誤りを見つける「デバッグ」作業も複雑になり、ユーザーに問題が発生したことを明確に伝えることも難しかったのだ。
このような課題を解決するために、JavaScriptに導入されたのがAggregateErrorという新しい機能である。これは複数のエラーを一つのオブジェクトにまとめてくれる便利な仕組みで、複雑な非同期処理におけるエラーの整理と、よりスマートな対応を可能にする。
具体的に、これまでのやり方では何が問題だったのかを見てみよう。例えば、複数のシステムからデータを取得しようと試みる場面を考える。JavaScriptのPromise.any()という機能は、複数の非同期処理を並行して実行し、そのうちどれか一つでも成功すればその結果を返す。しかし、もし実行したすべての非同期処理が失敗してしまった場合、従来のJavaScriptでは、個々のエラーをまとめて処理するための明確な方法がなかった。開発者は、それぞれの非同期処理が失敗したかどうかを個別にチェックし、手動でどのアクションが失敗したかを判断する必要があった。これは特に、処理が失敗した場合に何度か再試行(リトライ)するようなロジックを組み込む際に顕著で、どのエラーが原因で再試行するのかを判断するために、煩雑な条件分岐やループ処理を記述しなければならなかった。結果として、コードは長くなり、保守も難しくなる傾向にあった。
また、ユーザーがウェブサイトのフォームに入力する情報を検証する「フォームバリデーション」の場面でも同様の問題が発生していた。例えば、ユーザー名、メールアドレス、年齢といった複数の項目をチェックする場合を想像してみる。従来の多くのバリデーション関数では、一つでもエラーが見つかるとそこで処理を中断し、最初に見つかったエラーだけをユーザーに提示することが多かった。例えば、名前が空欄、メールアドレスが不正、年齢が規定未満という三つの問題があったとしても、最初に「名前は必須です」というエラーが表示され、ユーザーがそれを修正して再度送信すると、「メールアドレスが不正です」と別のエラーが初めて表示される、といった具合だ。これではユーザーは何度もフォームを修正して送信し直す必要があり、非常に不便である。開発者にとっても、すべてのエラーを一度に収集して表示するためには、複雑なロジックを独自に実装する必要があり、これもまたコードを複雑にする原因となっていた。複数のtry/catchブロックをコードのあちこちに記述することになり、コードの見通しが悪くなりがちだった。
ここでAggregateErrorが大きな力を発揮する。AggregateErrorは、その名の通り「集約されたエラー」を意味し、複数のエラーオブジェクトを配列として内部に保持できる特別なエラーオブジェクトである。これは、JavaScriptが提供する標準のエラーオブジェクトの一つとして定義されている。
Promise.any()との組み合わせでAggregateErrorがどのように機能するかを見てみよう。先述の通り、Promise.any()は一つでも成功するプロミスがあればその結果を返す。しかし、もし与えられたすべてのプロミスが失敗した場合に限り、特別なエラーとしてAggregateErrorを発生させる。このとき、AggregateErrorオブジェクトのerrorsというプロパティには、失敗したそれぞれのプロミスが返した個々のエラーオブジェクトが配列として格納されている。これにより、開発者はtry/catchブロックでAggregateErrorを捕捉するだけで、すべての失敗したプロミスに関する情報を一度に得られるようになる。個別にエラーを追跡したり、どのプロミスが失敗したかを手動で判定したりする手間が不要になるのだ。例えば、複数のAPIからのデータ取得がすべて失敗した場合、AggregateErrorを捕まえ、そのerrorsプロパティをループ処理で確認すれば、どのアクシデントが発生したかを詳細に把握し、再試行するか、最終的なエラーメッセージをユーザーに提示するかといった適切な対応をスムーズに実装できる。コードは格段にシンプルになり、エラーハンドリングのロジックもクリアになる。
フォームバリデーションにおいても、AggregateErrorは非常に有効な手段となる。従来の、最初に見つかったエラーで処理を中断するのではなく、AggregateErrorを使えば、すべてのバリデーションチェックを最後まで実行し、発生したエラーを一時的な配列にまとめておくことができる。そして、もしこのエラー配列に一つでもエラーが含まれていれば、そのエラー配列を引数としてAggregateErrorオブジェクトを作成し、それをスローする。こうすることで、try/catchブロックでAggregateErrorを捕捉した際に、e.errorsプロパティを通じてすべてのエラーメッセージにアクセスし、それらをまとめてユーザーに提示できるようになる。ユーザーは一度のフィードバックで、フォームのどこを修正すべきかをすべて把握できるため、体験が大幅に向上する。開発者にとっても、バリデーションロジックが一箇所に集約され、コードの重複が減り、管理が非常に楽になる。
このように、AggregateErrorは複数のエラーを効率的に管理するための強力なツールであり、非同期処理における複雑なエラーフローを整理し、コードを清潔に保ち、デバッグを容易にする。また、ユーザーへのフィードバックを改善し、より良いユーザー体験を提供することにも貢献する。特に、フォームの入力検証のように、一度に複数の問題点を指摘する必要がある場面や、複数のデータソースから情報を取得するような非同期処理において、AggregateErrorはその真価を発揮するだろう。これからは、個々のエラーに右往左往するのではなく、AggregateErrorを活用して、エラーを「グループ化」してスマートに対処することが、現代のJavaScript開発における重要なテクニックとなる。