Skip to content

Commit

Permalink
feat: ErrorCauseへの対応 (#1732)
Browse files Browse the repository at this point in the history
* feat: add a `error-cause` section to `error-try-catch`

See. #1714

* chore: add a error-cause to `error-try-catch` conclusion section

* chore: Use cause property in ajaxapp/promise example codes

* chore: access to cause property in `Error cause` section's example code

* refactor: Exec `npm run textlint:fix`

* chore: align with other heading expressions

* chore: change from active form to passive form

See. #1732 (comment)

Co-authored-by: azu <azu@users.noreply.github.com>

* chore: add conjunction

Co-authored-by: Suguru Inatomi <suguru.inatomi@gmail.com>

* chore: 表記ゆれの統一(送出 -> 投げられる)

Co-authored-by: azu <azu@users.noreply.github.com>

* chore: cut out a example code

* fix: remove unnecessary console.error

* fix: Error Causeの説明をより丁寧にする

* fix: remove logging cause property

* fix: exec `npm run textlint:fix`

* fix: broken test

Co-authored-by: azu <azu@users.noreply.github.com>

* chore: Remove empty lines

Co-authored-by: azu <azu@users.noreply.github.com>

* fix: add cause description

* fix: use Number.parseInt instead of parseInt

Co-authored-by: azu <azu@users.noreply.github.com>

* chore: change function definition order safeParseInt and sumNumStrings

---------

Co-authored-by: azu <azu@users.noreply.github.com>
Co-authored-by: Suguru Inatomi <suguru.inatomi@gmail.com>
  • Loading branch information
3 people committed Mar 27, 2024
1 parent 80be4a7 commit 76dd4c1
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 0 deletions.
34 changes: 34 additions & 0 deletions source/basic/error-try-catch/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,39 @@ MDNの[JavaScriptエラーリファレンス][]には、ブラウザが投げる
また、ほとんどのブラウザには`console.log``console.error`の出力をフィルタリングできる機能が備わっています。
ただのログ出力には`console.log`を使い、エラーに関するログ出力には`console.error`を使うことで、ログの重要度が区別しやすくなります。

## [ES2022] Error Cause {#error-cause}

エラーをキャッチした際、新しいメッセージを持たせた別のエラーを再度投げ直すことで、デバッグに役立つ情報を付与できます。
これを実現する時に、新しくErrorオブジェクトを作成してthrowすることで実現できます。
しかし、この方法には本来のエラーのスタックトレースが失われるという問題があります。

{{book.console}}
<!-- doctest:Error -->
```js
function somethingWork() {
throw new Error("本来のエラー");
}

try {
somethingWork();
} catch (error) {
// `error` が持っていたスタックトレースが失われるため、実際にエラーが発生した場所がわからなくなる
throw new Error("somethingWork関数でエラーが発生しました");
}
```

このスタックトレースが失われる問題を解決するには、ES2022で追加されたErrorの`cause`オプションが利用できます。
新しいエラーオブジェクトを作成する際に、第2引数の`cause`オプションに本来のエラーオブジェクトを渡すことで、本来のスタックトレースを保持できます。

{{book.console}}
[import, error-cause/index.js](src/error-cause/index.js)

このスクリプトを読み込むと、`sumNumsStrings` の例外に `safeParseInt` から投げられたスタックトレースが付与された状態のエラーログがコンソールに出力されます。
ここではFirefoxにおける実行例を示します。


![safeParseIntのスタックトレースが含まれたconsole.errorの出力結果](./img/error-cause.png)

## まとめ {#conclusion}

この章では、例外処理とエラーオブジェクトについて学びました。
Expand All @@ -291,6 +324,7 @@ MDNの[JavaScriptエラーリファレンス][]には、ブラウザが投げる
- `throw`文は例外を投げることができ、`Error`オブジェクトを例外として投げる
- `Error`オブジェクトには、ECMAScript仕様や実行環境で定義されたビルトインエラーがある
- `Error`オブジェクトには、スタックトレースが記録され、デバッグに役立てられる
- Error Causeを使うことで、別のエラーのスタックトレースを引き継いだ新しいエラーを作成できる

[try...catch]: https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/try...catch
[throw]: https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/throw
Expand Down
Binary file added source/basic/error-try-catch/img/error-cause.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 27 additions & 0 deletions source/basic/error-try-catch/src/error-cause/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// 数値の文字列を受け取り数値を返す関数
// 'text' など数値にはならない文字列を渡された場合は例外を投げられる
function safeParseInt(numStr) {
const num = Number.parseInt(numStr, 10);
if (Number.isNaN(num)) {
throw new Error(`${numStr} is not a numeric`);
}
return num;
}

// 数字の文字列を二つ受け取り、合計を返す関数
function sumNumStrings(a, b) {
try {
const aNumber = safeParseInt(a);
const bNumber = safeParseInt(b);
return aNumber + bNumber;
} catch (e) {
throw new Error("Failed to sum a and b", { cause: e });
}
}

try {
// 数値にならない文字列 'string' を渡しているので例外が投げられる
sumNumStrings("string", "2");
} catch (err) {
console.error(`エラーが発生しました (${err})`);
}
6 changes: 6 additions & 0 deletions source/use-case/ajaxapp/promise/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ function fetchUserInfo(userId) {
displayView(view);
});
}
})
.catch(err => {
return Promise.reject(new Error(`Failed fetch user(id: ${userId}) info`, { cause: err }));
});
}
```
Expand Down Expand Up @@ -151,6 +154,9 @@ function fetchUserInfo(userId) {
// JSONオブジェクトで解決されるPromiseを返す
return response.json();
}
})
.catch(err => {
return Promise.reject(new Error(`Failed fetch user(id: ${userId}) info`, { cause: err }));
});
}
```
Expand Down

0 comments on commit 76dd4c1

Please sign in to comment.