# 【初心者向け】エラーを握りつぶすことの問題と対処法

> プログラミング初学者向けに、エラーを握りつぶすことの問題やエラーハンドリングの重要性、適切な対処方法について解説します。JavaScriptを用いた具体例を通して、デバッグやユーザー体験への影響を理解し、エラーを適切に管理するためのポイントを紹介します。

- 公開日: 2024-12-06
- 著者: そうま
- タグ: エンジニア, JavaScript
- URL: https://tech.anycloud.co.jp/articles/js-error-handling

---

今回はプログラミング初学者向けに、エラーを握りつぶすことの問題とエラーハンドリグについて解説します。

javascriptを用いて解説しますが、以下の2点は把握している前提で書いています。

-   jsの基本的な構文
-   try catchの使い方

## エラーを握りつぶすとは

エラーを握りつぶすとは、以下のようにでエラーをキャッチしたは良いが、エラーが発生したときの処理を何も書かかないことで、エラーが発生したことを分からなくてしまうことを言います。

```javascript
try {
  throw new Error('エラーメッセージ')
} catch (error) {
}
```

例えば、以下のコードを実行すると

```javascript
const throwError = () => {
	try {
	  throw new Error('エラーメッセージ')
	} catch (error) {
	}
}

const func = () => {
  console.log('start')
  throwError()
  console.log('finish')
}

func()
```

出力結果はstartとfinishが出力されるだけになります。

```javascript
start
finish
```

実際にはstartとfinishの出力の間でエラーが発生していますが、throwError関数でエラーを握りつぶしているためエラーが発生していることに気づくことができません。

エラーを握りつぶすことの問題は、主に2点あります。

-   デバッグが困難になる
-   ユーザー体験が悪い

### デバッグが困難になる

具体例で見たように、エラーを握りつぶすと実際にはエラーが発生しているが気付けない状態となるため、システムがなぜ動作しないのか、何が原因で動作していないのかを特定することが難しくなります。

### ユーザー体験が悪い

開発者がエラーの原因を把握できないということは、当然ユーザーもエラーの原因を把握することができません。

せめてエラーが発生していることが分かるようなアラートを出せれば良いですが、エラーを握りつぶしている場合、エラーが発生しているかどうかもユーザーに伝えることができなくなります。

## 対処方法

### ログを出力する

開発者がデバッグをしやすいように、エラーのログを出力するようにしましょう。

```javascript
const throwError = () => {
	try {
	  throw new Error('エラーメッセージ')
	} catch (error) {
	  // エラーのログを出力する
	  console.log(error)
	}
}

const func = () => {
  console.log('start')
  throwError()
  console.log('finish')
}

func()
```

出力結果

```javascript
start
Error: エラーメッセージ
finish
```

ログを出力するようにしたことで、エラーが発生していることに気付けるようになりました。

エラーが発生した箇所で処理を止めたい場合は、throwError関数のcatch内でエラーを投げるようにしましょう。

```javascript
const throwError = () => {
	try {
	  throw new Error('エラーメッセージ')
	} catch (error) {
	  throw new Error(error.message)
	}
}

const func = () => {
  console.log('start')
  throwError()
  console.log('finish')
}

func()
```

出力結果

```javascript
start
Error: エラーメッセージ
```

### ユーザーに通知する

開発者に分かりやすいように、ログを出力するとともに、必要に応じてユーザーにもエラーを確認できるようにしましょう。

```javascript
const throwError = () => {
	try {
	  throw new Error('エラーメッセージ')
	} catch (error) {
	  throw new Error(error.message)
	}
}

const func = () => {
  try {
    console.log('start')
	  throwError()
	  console.log('finish')
  } catch (error) {
    // アラートを出す
    alert('エラーが発生しました。')
  }
}

func()
```

これにより、ユーザーもエラーが発生していることが分かるようになり、操作ができないなどの問題があってもエラーが起きていることが原因だと分かります。

今回は簡易的にアラートを出していますが、実際のアプリケーションではエラーの詳細や解決策を示すとよりユーザー体験の向上に繋がります。

### 気をつけるべきポイント

エラーハンドリングは関数のネストが深くなったり、システムが大規模になってくるとより複雑になっていきます。

例えば、以下のコードを実行すると

```javascript
const throwError = () => {
	try {
	  throw new Error('エラーメッセージ')
	} catch (error) {
	  throw new Error(error.message)
	}
}

const func = () => {
  try {
    console.log('func start')
    throwError()
	  console.log('func finish')
  } catch (error) {
    console.log(error.message)
  }
 }

const main = () => {
  console.log('main start')
  func()
  console.log('main finish')
}

main()
```

出力結果は以下のようになります。

```javascript
main start
func start
エラーメッセージ
main finish
```

ここでのポイントは「main finish」が出力されていることです。

main関数ではエラーハンドリグを行っていないため、このような挙動になります。

これが期待通りの場合は問題ありませんが、throwErrorのエラーが発生した場合、main関数の処理も止めた場合には問題です。

main関数の処理も止めたい場合、どのように対処するべきでしょうか。

対処方法はいくつかありますが、例えば以下の2点があります。

-   func関数のcatch内でも、エラーを投げるようにする
-   func関数のtry catchをやめる

これらの共通点は、main関数にエラーを伝えていることです。

このように、システムが複雑になってきて階層が深くなると、エラーハンドリグをすべき場所、しなくても良い場所など、エラーを握りつぶさないために、正しくエラーを伝搬する必要がでてきます。

とりあえずtry catchを使用してログを出力すれば良い訳ではないので、エラーを適切に対処できているかは常に気をつけましょう。
