Skip to content

Commit 6c341eb

Browse files
committed
Docsify Auto Published
1 parent fbbcaa2 commit 6c341eb

File tree

3 files changed

+163
-1
lines changed

3 files changed

+163
-1
lines changed

_sidebar.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
- [Map](basic/js/map.md)
2626
- [Reduce](basic/js/reduce.md)
2727
- [正则替换](basic/js/regexp.md)
28+
- [异常捕获](basic/js/try-catch.md)
2829
- Node.js
2930
- [包管理](basic/node/pkg.md)
3031
- [Yarn进阶](basic/node/yarn.md)

basic/js/tricks.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,4 +166,4 @@ suite('iterator', function () {
166166
element.fireEvent('onchange');
167167
}
168168
};
169-
```
169+
```

basic/js/try-catch.md

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
# 异常捕获
2+
3+
## ES5 中的传统做法
4+
5+
假设代码块执行抛出错误 fail,那么捕获该错误的写法为:
6+
7+
```js
8+
try {
9+
// 代码块执行,并抛出 fail 错误
10+
throw new Error('fail');
11+
} catch (e) {
12+
console.log(e);
13+
}
14+
```
15+
16+
### 定时器
17+
18+
我们先来针对上面的代码改写一下,加入一个定时器。
19+
20+
```js
21+
try {
22+
setTimeout(()=>{
23+
throw new Error('fail');
24+
// Uncaught Error: fail
25+
}, 1000);
26+
} catch (e) {
27+
console.log(e);
28+
}
29+
```
30+
31+
像这样,将 try/catch 扔在定时器的外面,是无法捕获到内部的错误的。
32+
33+
正确的做法应该是:
34+
35+
```js
36+
setTimeout(()=>{
37+
try{
38+
throw new Error('fail');
39+
} catch (e) {
40+
console.log(e);
41+
}
42+
},1000);
43+
```
44+
45+
### Promise
46+
47+
```js
48+
function doSomething() {
49+
return new Promise((resolve, reject) => {
50+
// 同步代码中的 throw 可以被捕捉到
51+
throw new Error('fail');
52+
});
53+
}
54+
55+
doSomething()
56+
.then((x) => {
57+
console.log('success:', x);
58+
})
59+
.catch((err) => {
60+
console.log('fail:', err);
61+
});
62+
```
63+
64+
这样写是没有问题的,错误能够被捕获到。但只要稍微修改一下,可能就出现问题了。比如:
65+
66+
```js
67+
function doSomething() {
68+
return new Promise((resolve, reject) => {
69+
// 异步代码中的 throw 不能被 Promise 的 catch 捕捉到
70+
setTimeout(() => {
71+
throw new Error("fail");
72+
}, 1000);
73+
});
74+
}
75+
76+
doSomething()
77+
.then((x) => {
78+
console.log('success:', x);
79+
})
80+
.catch((err) => {
81+
console.log('fail:', err);
82+
});
83+
```
84+
85+
这里抛出但错误将不能被捕获。所以,在 Promise 中,我们一般通过 reject 来抛出错误。
86+
87+
```js
88+
function doSomething(x) {
89+
return new Promise((resolve, reject) => reject(x));
90+
}
91+
92+
doSomething('fail').then((x) => {
93+
console.log('success:', x);
94+
}).catch((err) => {
95+
console.log('fail:', err);
96+
});
97+
// fail: fail
98+
```
99+
100+
另外,还有一个比较有意思的细节,在 catch 之后继续添加 .then 会被继续执行。
101+
102+
```js
103+
function doSomething(x) {
104+
return new Promise((resolve, reject) => reject(x));
105+
}
106+
107+
doSomething('fail').then((x) => {
108+
console.log('success:', x);
109+
}).catch((err) => {
110+
console.log('fail:', err);
111+
// 这里可以写 return 给下面的方法继续执行
112+
}).then((x) => {
113+
console.log('continue:', x);
114+
});
115+
// fail: fail
116+
// continue: undefined
117+
```
118+
119+
### Async/Await
120+
121+
本质上来讲, Async/Await 是通过 Promise 实现,所以基本跟上面 Promise 所讲的差不多。
122+
123+
可以在 await 方法外嵌套 try/catch,类似这样:
124+
125+
```js
126+
function doSomething(x) {
127+
return new Promise((resolve, reject) => reject(x));
128+
}
129+
130+
(async () => {
131+
try {
132+
const result = await doSomething('fail');
133+
console.log('success:', result);
134+
// return 返回
135+
} catch (err) {
136+
console.log('fail:', err);
137+
// return 返回
138+
}
139+
})();
140+
// fail: fail
141+
```
142+
143+
但这里就有一个问题,比如函数需要有返回,那么返回的语句就需要写两次,正常但时候返回结果,错误的时候,返回一个 `throw new Error()` 或者其他的。有一个小的窍门,可以这样写:
144+
145+
```js
146+
function doSomething(x) {
147+
return new Promise((resolve, reject) => reject(x));
148+
}
149+
150+
(async () => {
151+
const result = await doSomething('fail').catch((err) => {
152+
console.log('fail:', err);
153+
return 0; // 默认值
154+
});
155+
console.log('success:', result);
156+
})();
157+
// fail: fail
158+
// success: 0
159+
```
160+
161+
在错误捕获到之后,重新分配一个默认值,让代码继续运行。

0 commit comments

Comments
 (0)