0%

不要在Promise中使用throw

  1. 在Promise中抛出异常的方式
    1. 直接抛出
    2. 在回调中抛出

在Promise中抛出异常的方式

直接抛出

例如要创建一个同步函数,在该函数中抛出一个异常,可以这么写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const func = (): Promise<string> => {
return new Promise((resolve, reject) => {
throw new Error('123');
})
}

(async () => {
try {
const result = await func();
console.log(result);
} catch (e) {
console.error(e instanceof Error ? e.stack : e);
}

console.log('hello');
})();

输出结果为:

1
2
3
4
5
6
7
8
9
10
11
12
Error: 123
at D:\codes\node\test\a.ts:3:15
at new Promise (<anonymous>)
at func (D:\codes\node\test\a.ts:2:12)
at D:\codes\node\test\a.ts:9:30
at Object.<anonymous> (D:\codes\node\test\a.ts:16:3)
at Module._compile (internal/modules/cjs/loader.js:1085:14)
at Module.m._compile (D:\codes\node\test\node_modules\ts-node\src\index.ts:1371:23)
at Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
at Object.require.extensions.<computed> [as .ts] (D:\codes\node\test\node_modules\ts-node\src\index.ts:1374:12)
at Module.load (internal/modules/cjs/loader.js:950:32)
hello

throw new Error('123');写成reject(new Error('123'));效果一致。

在回调中抛出

如果在Promise中存在一个回调函数,直接使用throw就会出现问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const func = (): Promise<string> => {
return new Promise((resolve, reject) => {
setTimeout(() => {
throw new Error('123');
}, 3000);
})
}

(async () => {
try {
const result = await func();
console.log(result);
} catch (e) {
console.error(e instanceof Error ? e.stack : e);
}

console.log('hello');
})();
1
2
3
4
5
6
7
D:\codes\node\test\a.ts:4
throw new Error('123');
^
Error: 123
at Timeout._onTimeout (D:\codes\node\test\a.ts:4:19)
at listOnTimeout (internal/timers.js:557:17)
at processTimers (internal/timers.js:500:7)

这时候reject函数的作用就体现出来了,因为throw抛出异常只能由所在的函数所捕捉,无法向上传递,因此在回调函数里面抛出的异常通常由提供回调函数的接口来处理,而要实现向上的传播,就要使用reject

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const func = (): Promise<string> => {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('123'));
}, 3000);
})
}

(async () => {
try {
const result = await func();
console.log(result);
} catch (e) {
console.error(e instanceof Error ? e.stack : e);
}

console.log('hello');
})();
1
2
3
4
5
6
# 三秒后...
Error: 123
at Timeout._onTimeout (D:\codes\node\test\a.ts:4:20)
at listOnTimeout (internal/timers.js:557:17)
at processTimers (internal/timers.js:500:7)
hello