Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit ff1ee4d

Browse files
committed
修正对 catch 捕获错误的讲述错误
1 parent d306d25 commit ff1ee4d

File tree

3 files changed

+74
-6
lines changed

3 files changed

+74
-6
lines changed

‎02-3-promise-error.md‎

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,57 @@ Promise 会自动捕获内部异常,并交给 `rejected` 响应函数处理。
1010
```javascript
1111
new Promise( resolve => {
1212
setTimeout( () => {
13-
thrownewError('bye');
13+
resolve();
1414
}, 2000);
15+
throw new Error('bye');
1516
})
1617
.then( value => {
1718
console.log( value + ' world');
1819
})
1920
.catch( error => {
2021
console.log( 'Error: ', error.message);
22+
});
2123

22-
// 输出:
23-
// (2秒后)Error: bye
24-
// at Timeout.setTimeout [as _onTimeout] (/path/to/error.js:7:11)
24+
// 立刻输出:
25+
// Error: bye
26+
```
27+
28+
可以看到,原定2s之后 `resolve()` 并没有出现,因为在 Promise 的执行器里抛出了错误,所以立刻跳过了 `.then()`,进入 `.catch()` 处理异常。
29+
30+
这里需要注意,如果把抛出错误的语句放到回调函数里,则是另外一副光景:
31+
32+
```javascript
33+
new Promise( resolve => {
34+
setTimeout( () => {
35+
throw new Error('bye');
36+
}, 2000);
37+
})
38+
.then( value => {
39+
console.log( value + ' world');
40+
})
41+
.catch( error => {
42+
console.log( 'It\'s an Error: ', error.message);
43+
});
44+
45+
// (2s之后)输出:
46+
// ./code/2-3-catch-error.js:3
47+
// throw new Error('bye');
48+
// ^
49+
50+
// Error: bye
51+
// at Timeout.setTimeout [as _onTimeout] (/Users/meathill/Documents/Book/javascript-async-tutorial/code/2-3-catch-error.js:3:11)
2552
// at ontimeout (timers.js:488:11)
2653
// at tryOnTimeout (timers.js:323:5)
2754
// at Timer.listOnTimeout (timers.js:283:5)
2855
```
2956

30-
可以看到,2秒之后,因为在 Promise 的执行器里抛出了错误,所以跳过了 `.then()`,进入 `.catch()` 处理异常。
57+
正如[异步的问题](./01-2-issue.md)分析的那样,异步回调中,异步函数的栈,和回调函数的栈,**不是**一个栈。所以 Promise 的执行器只能捕获到异步函数抛出的错误,无法捕获回调函数抛出的错误。
58+
59+
回到上面这段代码,当回调函数抛出错误时,我们没有捕获处理,运行时就出面捕获了,于是报错、回调栈被终结。此时,Promise 对象的状态并未被改变,所以下面的 `.then()` 响应函数和 `.catch()` 响应函数都没有触发,我们看到的,只是默认的错误输出。(2017年07月19日 更新)
60+
61+
这也印证了 Promise 的问题:它没有引入新的语法元素,所以无法摆脱栈断裂带来的问题。在错误处理方面,它只是"能用",并不好用,无法达到之前的开发体验。
62+
63+
### `reject`
3164

3265
正如我们前面所说,`.then(fulfilled, reject)` 其实接收两个参数,分别作为成功与失败的回调。不过在实践中,我更推荐上面的做法,即不传入第二个参数,而是把它放在后面的 `.catch()` 里面。这样有两个好处:
3366

@@ -79,7 +112,9 @@ new Promise(resolve => {
79112

80113
## 小结
81114

82-
简单总结一下 Promise 的错误处理。与异步回调相比,它的作用略强,可以抛出和捕获错误,基本可以按照预期的状态执行。然而它仍然不是真正的 `try/catch/throw``.catch()` 也使用 `Promise.resolve()` 返回 `fulfilled` 状态的 Promise 实例,所以它后面的 `.then()` 会继续执行,在队列很长的时候,也容易出错,请大家务必小心。
115+
简单总结一下 Promise 的错误处理。与异步回调相比,它的作用略强,可以抛出和捕获错误,基本可以按照预期的状态执行。然而它仍然不是真正的 `try/catch/throw`
116+
117+
`.catch()` 也使用 `Promise.resolve()` 返回 `fulfilled` 状态的 Promise 实例,所以它后面的 `.then()` 会继续执行,在队列很长的时候,也容易出错,请大家务必小心。
83118

84119
另外,所有执行器和响应函数里的错误都不会真正进入全局环境,所以我们有必要在所有队列的最后一步增加一个 `.catch()`,防止遗漏错误造成意想不到的问题。
85120

‎code/2-3-1-catch.js‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
new Promise( resolve => {
2+
setTimeout( () => {
3+
resolve();
4+
}, 2000);
5+
throw new Error('bye');
6+
})
7+
.then( value => {
8+
console.log( value + ' world');
9+
})
10+
.catch( error => {
11+
console.log( 'Error: ', error.message);
12+
});

‎code/2-3-2-catch.js‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
new Promise( resolve => {
2+
setTimeout( () => {
3+
throw new Error('bye');
4+
}, 2000);
5+
})
6+
.then( value => {
7+
console.log( value + ' world');
8+
})
9+
.catch( error => {
10+
console.log( 'It\'s an Error: ', error.message);
11+
});
12+
13+
// ./code/2-3-catch-error.js:3
14+
// throw new Error('bye');
15+
// ^
16+
17+
// Error: bye
18+
// at Timeout.setTimeout [as _onTimeout] (/Users/meathill/Documents/Book/javascript-async-tutorial/code/2-3-catch-error.js:3:11)
19+
// at ontimeout (timers.js:488:11)
20+
// at tryOnTimeout (timers.js:323:5)
21+
// at Timer.listOnTimeout (timers.js:283:5)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /