You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 1-js/10-error-handling/2-custom-errors/article.md
+32-4
Original file line number
Diff line number
Diff line change
@@ -215,11 +215,39 @@ Now custom errors are much shorter, especially `ValidationError`, as we got rid
215
215
216
216
The purpose of the function `readUser` in the code above is "to read the user data". There may occur different kinds of errors in the process. Right now we have `SyntaxError` and `ValidationError`, but in the future `readUser` function may grow and probably generate other kinds of errors.
217
217
218
-
The code which calls `readUser` should handle these errors. Right now it uses multiple `if`s in the `catch` block, that check the class and handle known errors and rethrow the unknown ones. But if the `readUser` function generates several kinds of errors, then we should ask ourselves: do we really want to check for all error types one-by-one in every code that calls `readUser`?
218
+
The code which calls `readUser` should handle these errors. Right now it uses multiple `if`s in the `catch` block, that check the class and handle known errors and rethrow the unknown ones.
219
219
220
-
Often the answer is "No": the outer code wants to be "one level above all that", it just wants to have some kind of "data reading error" -- why exactly it happened is often irrelevant (the error message describes it). Or, even better, it could have a way to get the error details, but only if we need to.
220
+
The scheme is like this:
221
221
222
-
So let's make a new class `ReadError` to represent such errors. If an error occurs inside `readUser`, we'll catch it there and generate `ReadError`. We'll also keep the reference to the original error in its `cause` property. Then the outer code will only have to check for `ReadError`.
222
+
```js
223
+
try {
224
+
...
225
+
readUser() // the potential error source
226
+
...
227
+
} catch (err) {
228
+
if (err instanceof ValidationError) {
229
+
// handle validation errors
230
+
} elseif (err instanceofSyntaxError) {
231
+
// handle syntax errors
232
+
} else {
233
+
throw err; // unknown error, rethrow it
234
+
}
235
+
}
236
+
```
237
+
238
+
In the code above we can see two types of errors, but there can be more.
239
+
240
+
If the `readUser` function generates several kinds of errors, then we should ask ourselves: do we really want to check for all error types one-by-one every time?
241
+
242
+
Often the answer is "No": we'd like to be "one level above all that". We just want to know if there was a "data reading error" -- why exactly it happened is often irrelevant (the error message describes it). Or, even better, we'd like to have a way to get the error details, but only if we need to.
243
+
244
+
The technique that we describe here is called "wrapping exceptions".
245
+
246
+
1. We'll make a new class `ReadError` to represent a generic "data reading" error.
247
+
2. The function `readUser` will catch data reading errors that occur inside it, such as `ValidationError` and `SyntaxError`, and generate `ReadError` instead.
248
+
3. The `ReadError` object will keep the reference to the original error in its `cause` property.
249
+
250
+
Then the code that calls `readUser` will only have to check for `ReadError`, not for every kind of data reading errors.
223
251
224
252
Here's the code that defines `ReadError` and demonstrates its use in `readUser` and `try..catch`:
225
253
@@ -293,7 +321,7 @@ In the code above, `readUser` works exactly as described -- catches syntax and v
293
321
294
322
So the outer code checks `instanceof ReadError` and that's it. No need to list all possible error types.
295
323
296
-
The approach is called "wrapping exceptions", because we take "low level exceptions" and "wrap" them into `ReadError` that is more abstract and more convenient to use for the calling code. It is widely used in object-oriented programming.
324
+
The approach is called "wrapping exceptions", because we take "low level" exceptions and "wrap" them into `ReadError` that is more abstract. It is widely used in object-oriented programming.
0 commit comments