Skip to content

1-js/08-error-handling/2-custom-errors#115

Merged
leviding merged 18 commits intojavascript-tutorial:zh-hansfrom
lihanxiang:translation/js-08
Jun 19, 2018
Merged

1-js/08-error-handling/2-custom-errors#115
leviding merged 18 commits intojavascript-tutorial:zh-hansfrom
lihanxiang:translation/js-08

Conversation

@lihanxiang
Copy link
Copy Markdown
Contributor

@lihanxiang lihanxiang commented Jun 6, 2018

resolve #108

@lihanxiang lihanxiang changed the title 自定义以及拓展错误 1-js/08-error-handling/2-custom-errors Jun 6, 2018
@sakila1012
Copy link
Copy Markdown

校对认领

@leviding
Copy link
Copy Markdown
Member

leviding commented Jun 8, 2018

@sakila1012 ok

创造一个继承自内置类 `SyntaxError` 的 `FormatError` 类。

It should support `message`, `name` and `stack` properties.
它应该支持 `message` `name` `stack` 属性。
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

它应该支持 messagenamestack 属性。

当我们在进行开发的时候,通常需要属于我们自己的错误类来反映任务中可能出现的特殊情况。对于网络操作错误,我们需要 `HttpError`,对于数据库操作错误,我们需要 `DbError`,对于搜索操作错误,我们需要 `NotFoundError`,等等。

Our errors should support basic error properties like `message`, `name` and, preferably, `stack`. But they also may have other properties of their own, e.g. `HttpError` objects may have `statusCode` property with a value like `404` or `403` or `500`.
我们自定义的错误应该具有基本的错误属性,例如 `message``name` 以及更加详细的 `stack`。但是它们也会有属于自己的属性。举个例子,`HttpError`对象会有一个 `statusCode` 属性,取值可能为 `404``403` `500` 等。
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我们自定义的错误应该具有基本的错误属性,例如 messagename 以及更加详细的 stack。但是它们也会有属于自己的属性。举个例子,HttpError 对象会有一个 statusCode 属性,取值可能为 404403500 等。

@@ -1,33 +1,33 @@
# Custom errors, extending Error
# 自定义以及拓展错误
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

自定义以及继承错误

但即使是格式正确的 `json`,也并不表示它就是可用的,对吧?它有可能会遗漏一些必要的数据。例如,缺失了对用户有必要的 `name` `age` 属性。

Our function `readUser(json)` will not only read JSON, but check ("validate") the data. If there are no required fields, or the format is wrong, then that's an error. And that's not a `SyntaxError`, because the data is syntactically correct, but another kind of error. We'll call it `ValidationError` and create a class for it. An error of that kind should also carry the information about the offending field.
函数 `readUser(json)` 不止会读取 JSON,也会检查(验证)数据的。如果没有所需要的属性,或者格式不正确,就会发生错误。而这不是 `SyntaxError`,因为数据在语法上时正确的,但是有其他的错误。我们称之为 `ValidationError` 并且为之创建一个类。这种类型的错误也应该承载缺少的字段的信息。
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

函数 readUser(json) 不仅会读取 JSON,也会检查(验证)数据。

使用 `instanceof` 的做法会好很多,因为我们在以后会扩展 `ValidationError`,创造一个它的子类型,例如 `PropertyRequiredError`。而 `instanceof` 对于新的继承类也适用。所以这是个长远的保证。

Also it's important that if `catch` meets an unknown error, then it rethrows it in the line `(**)`. The `catch` only knows how to handle validation and syntax errors, other kinds (due to a typo in the code or such) should fall through.
还有一点很重要,在 `catch` 语句捕捉到未知的错误时,它会抛出在行 `(**)` 处重新抛出,`catch` 语句仅仅知道如何处理验证和语法错误,而其他错误不应该被捕获。
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

还有一点很重要,在 catch 语句捕捉到未知的错误时,它会在抛出行 (**) 处重新抛出,catch 语句仅仅知道如何处理验证和语法错误,而其他错误不应该被捕获。

这个 `PropertyRequiredError` 十分容易上手:我们只需要传递属性名:`new PropertyRequiredError(property)`。易懂的 `message` 属性将会由构造器提供。

Please note that `this.name` in `PropertyRequiredError` constructor is again assigned manually. That may become a bit tedius -- to assign `this.name = <class name>` when creating each custom error. But there's a way out. We can make our own "basic error" class that removes this burden from our shoulders by using `this.constructor.name` for `this.name` in the constructor. And then inherit from it.
需要注意的是,在 `PropertyRequiredError` 构造器中的 `this.name` 是再次进行手动赋值的。这可能会造成冗余 —— 在创建每个自定义错误的时候都要进行赋值 `this.name = <class name>`。但这并不是唯一的办法。我们可以创建自己的“基础异常”类,通过将 `this.constructor.name` 赋值给 `this.name`,然后再进行继承。
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But there's a way out. We can make our own "basic error" class that removes this burden from our shoulders by using this.constructor.name for this.name in the constructor.这一句没有翻译完,遗漏部分

```

In the code above, `readUser` works exactly as described -- catches syntax and validation errors and throws `ReadError` errors instead (unknown errors are rethrown as usual).
上述代码中, `readUser` 正如描述的一样正常工作 —— 捕获语法以及验证的异常并且使用抛出 `ReadError`用来代替之前的行为(未知的异常依旧重新抛出)。
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

上述代码中, readUser 正如描述的一样正常工作 —— 捕获语法以及验证的异常并且使用抛出 ReadError 异常用来代替之前的行为(未知的异常依旧重新抛出)。

所以外部代码负责检测 `instanceof ReadError`,不必列出所有可能的异常类型。

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.
这种途径称为“包装异常”,因为我们将“低级别的异常”包装为 `ReadError` ,这会使得调用代码更加的方便。它在面向对象编程中广泛使用。
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这种途径称为“包装异常”,因为我们将“低级别的异常”包装为 ReadError ,这会使得调用代码更加的抽象和方便。它在面向对象编程中广泛使用。

@leviding leviding added the WIP Work in process label Jun 11, 2018
@MeFelixWang
Copy link
Copy Markdown

@leviding 校对认领

Copy link
Copy Markdown

@MeFelixWang MeFelixWang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我是第一次参与校对,提出的review多数是针对的注释没有翻译,有不对的地方还请包涵

在这里面,我们使用 `JSON.parse`。如果它接收到错误的 `json`,就会抛出 `SyntaxError`

But even if `json` is syntactically correct, that doesn't mean that it's a valid user, right? It may miss the necessary data. For instance, if may not have `name` and `age` properties that are essential for our users.
但即使是格式正确的 `json`,也并不表示它就是可用的,对吧?它有可能会遗漏一些必要的数据。例如,缺失了对用户有必要的 `name` `age` 属性。
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

『例如,缺失了对用户有必要的 nameage 属性』=>『例如,缺失了对于用户所必需的 nameage 属性』

但即使是格式正确的 `json`,也并不表示它就是可用的,对吧?它有可能会遗漏一些必要的数据。例如,缺失了对用户有必要的 `name` `age` 属性。

Our function `readUser(json)` will not only read JSON, but check ("validate") the data. If there are no required fields, or the format is wrong, then that's an error. And that's not a `SyntaxError`, because the data is syntactically correct, but another kind of error. We'll call it `ValidationError` and create a class for it. An error of that kind should also carry the information about the offending field.
函数 `readUser(json)` 不仅会读取 JSON,也会检查(验证)数据。如果没有所需要的属性,或者格式不正确,就会发生错误。而这不是 `SyntaxError`,因为数据在语法上时正确的,但是有其他的错误。我们称之为 `ValidationError` 并且为之创建一个类。这种类型的错误也应该承载缺少的字段的信息。
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

『如果没有所需要的属性,或者格式不正确,就会发生错误。』=>『如果没有所需要的字段,或者格式不正确,那也是错误。』

但即使是格式正确的 `json`,也并不表示它就是可用的,对吧?它有可能会遗漏一些必要的数据。例如,缺失了对用户有必要的 `name` `age` 属性。

Our function `readUser(json)` will not only read JSON, but check ("validate") the data. If there are no required fields, or the format is wrong, then that's an error. And that's not a `SyntaxError`, because the data is syntactically correct, but another kind of error. We'll call it `ValidationError` and create a class for it. An error of that kind should also carry the information about the offending field.
函数 `readUser(json)` 不仅会读取 JSON,也会检查(验证)数据。如果没有所需要的属性,或者格式不正确,就会发生错误。而这不是 `SyntaxError`,因为数据在语法上时正确的,但是有其他的错误。我们称之为 `ValidationError` 并且为之创建一个类。这种类型的错误也应该承载缺少的字段的信息。
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

『因为数据在语法上时正确的』=>『因为数据在语法上是正确的』

代码如下:

```js
// The "pseudocode" for the built-in Error class defined by JavaScript itself
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

注释也要翻译:『The "pseudocode" for the built-in Error class defined by JavaScript itself』=>『由JavaScript本身定义的内置错误类“伪代码”』

@@ -40,7 +40,7 @@ class Error {
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

注释也要翻译:『(different names for different built-in error classes)』=>『(不同内置错误类别的名称)』

- We can inherit from `Error` and other built-in error classes normally, just need to take care of `name` property and don't forget to call `super`.
- Most of the time, we should use `instanceof` to check for particular errors. It also works with inheritance. But sometimes we have an error object coming from the 3rd-party library and there's no easy way to get the class. Then `name` property can be used for such checks.
- Wrapping exceptions is a widespread technique when a function handles low-level exceptions and makes a higher-level object to report about the errors. Low-level exceptions sometimes become properties of that object like `err.cause` in the examples above, but that's not strictly required.
- 我们能够继承 `Error` 以及其他内置的类,只需要注意 `name` 属性以及调用 `super`
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

『我们能够继承 Error 以及其他内置的类,只需要注意 name 属性以及调用 super。』=>『我们能够正常地继承 Error 以及其他内置的错误类,只需要注意 name 属性以及不要忘了调用 super。』

- Wrapping exceptions is a widespread technique when a function handles low-level exceptions and makes a higher-level object to report about the errors. Low-level exceptions sometimes become properties of that object like `err.cause` in the examples above, but that's not strictly required.
- 我们能够继承 `Error` 以及其他内置的类,只需要注意 `name` 属性以及调用 `super`
- 大多数时候,我们应该使用 `instanceof` 来检测一些特定的异常。它也能够在继承中使用。但有时我们会发现来自第三方库的异常,并且不容易得到它的类。那么 `name` 属性就可用于这一类的检测。
- 包装异常是一种广泛应用的技术,当一个函数处理低级别的异常时,用一个高级别的对象来报告错误。低级别的异常有时会变成这个对象的属性,就像上面例子中的 `err.cause`,但这不是严格的要求。
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

『包装例外是一种广泛应用的技术,当一个函数处理低级别的异常时,用一个高级别的对象来报告异常。低级别的异常有时会变成这个对象的属性,就像上面例子中的 err.cause,但这并不严格要求。』

现在的自定义错误更加的简洁,特别是 `ValidationError`,我们在其构造器中删除了 `"this.name = ..."` 这一行。

## Wrapping exceptions
## 包装异常
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

『包装异常』=>『包装例外』

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

感觉翻译为 异常 会更合适一些吧

在我们进行开发时,我们自己的异常类通常是有层次结构的,例如 `HttpTimeoutError` 可能继承自 `HttpError` 等。

## Extending Error
## 可扩展错误
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

『可扩展错误』=>『扩展错误』

@@ -1,33 +1,33 @@
# Custom errors, extending Error
# 自定义以及继承错误
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

『自定义以及继承错误』=>『自定义错误及扩展错误』

@MeFelixWang
Copy link
Copy Markdown

@leviding @lihanxiang 校对完成

@leviding leviding removed WIP Work in process 校对认领 labels Jun 12, 2018
@leviding
Copy link
Copy Markdown
Member

@lihanxiang 再修改下吧

@leviding leviding added enhancement New feature or request and removed enhancement New feature or request labels Jun 12, 2018
@leviding leviding added WIP Work in process enhancement New feature or request and removed enhancement New feature or request labels Jun 13, 2018
Copy link
Copy Markdown
Member

@leviding leviding left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lihanxiang 有些问题,修改一下,注意哈。

创造一个继承自内置类 `SyntaxError` 的 `FormatError` 类。

It should support `message`, `name` and `stack` properties.
它应该支持 `message` `name` `stack` 属性。
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

逗号后多了一个空格

alert( err instanceof SyntaxError ); // true (because inherits from SyntaxError)
```
alert( err instanceof SyntaxError ); // true (因为它继承自 SyntaxError)
```
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

结尾多了一个空格

alert( err instanceof FormatError ); // true
alert( err instanceof SyntaxError ); // true (because inherits from SyntaxError)
```
alert( err instanceof SyntaxError ); // true (因为它继承自 SyntaxError)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true (因为它继承自 SyntaxError) => true(因为它继承自 SyntaxError)

翻译的内容这里括号用全角,且前后不加空格

当我们在进行开发的时候,通常需要属于我们自己的错误类来反映任务中可能出现的特殊情况。对于网络操作错误,我们需要 `HttpError`,对于数据库操作错误,我们需要 `DbError`,对于搜索操作错误,我们需要 `NotFoundError`,等等。

Our errors should support basic error properties like `message`, `name` and, preferably, `stack`. But they also may have other properties of their own, e.g. `HttpError` objects may have `statusCode` property with a value like `404` or `403` or `500`.
我们自定义的错误应该具有基本的错误属性,例如 `message``name` 以及更加详细的 `stack`。但是它们也会有属于自己的属性。举个例子,`HttpError`对象会有一个 `statusCode` 属性,取值可能为 `404``403` `500` 等。
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HttpError 和后面的汉字之间加空格

我们的 `ValidationError` 类应该继承自内置的 `Error` 类。

That class is built-in, but we should have its approximate code before our eyes, to understand what we're extending.
`Error` 类是内置的,但是我们需要看一下大致的代码,来理解我们需要扩展什么。
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

本段开头多了一个空格

## 更进一步的继承

The `ValidationError` class is very generic. Many things may go wrong. The property may be absent or it may be in a wrong format (like a string value for `age`). Let's make a more concrete class `PropertyRequiredError`, exactly for absent properties. It will carry additional information about the property that's missing.
`ValidationError` 类是十分通用的。因此可能会在某些方面出错。属性可能缺失,格式可能发生错误(例如 `age` 属性的值为一个字符串)。让我们来创造一个更加具体的类 `PropertyRequiredError`,为属性缺失的错误而量身定做的。它将会承载属性缺失的相关信息。
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image
多余空格

}

// Working example with try..catch
// try..catch实例
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image
中英文之间要有空格


// name is correct
alert( new PropertyRequiredError("field").name ); // PropertyRequiredError
alert( new PropertyRequiredError("field").name ); // 必有属性错误
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这句的注释就不翻译了,因为这是函数名吧。文中其他位置是否有类似的情况?注意一下。

*!*
alert(e);
// Original error: SyntaxError: Unexpected token b in JSON at position 1
// 原错误:语法错误:在位置1处不应有 b
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

数字和中文之间也要空格

```

In the code above, `readUser` works exactly as described -- catches syntax and validation errors and throws `ReadError` errors instead (unknown errors are rethrown as usual).
上述代码中, `readUser` 正如描述的一样正常工作 —— 捕获语法以及验证的异常并且抛出 `ReadError` 异常用来代替之前的行为(未知的异常依旧重新抛出)。
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image
多余空格

@leviding leviding added the enhancement New feature or request label Jun 18, 2018
@leviding leviding removed the enhancement New feature or request label Jun 19, 2018
@leviding leviding merged commit 3c91180 into javascript-tutorial:zh-hans Jun 19, 2018
@leviding leviding added 翻译完成 and removed WIP Work in process 正在校对 labels Jun 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants