常见错误处理
RangeError:范围错误,代码中使用了超出范围的数值
ReferenceError:引用错误,引用的变量/函数不存在
SyntaxError:语法解析错误
TypeError:类型错误,例如对非对象类型使用对象方法、对非函数类型使用函数调用操作符等
URIError:URI 错误,
decodeURI('%')
代码中使用了不合法的 URIEvalError:
eval()
InternalError:调用栈溢出
异步错误和 try/catch
Error 对象只有在被抛出时才会成为异常。
try/catch 可以捕获同步函数中的错误。
try catch 无法捕获异步函数中的错误
实例代码:
// 异步任务
const task = () => {
setTimeout(() => {
throw new Error('async error');
}, 1000);
};
// 主任务
function main() {
try {
task();
} catch (e) {
console.log(e, 'err');
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
这种情况下 main 是无法 catch error,原因是异步代码并不在 try catch 上下文中执行。异步任务由 eventloop 加入任务队列,并取出入栈(js 主进程)执行,而当 task 取出执行的时候, main 的栈已经退出了,也就是上下文环境已经改变,所以 main 无法捕获 task 的错误。
用 Promise 捕获异步错误
function task() {
new Promise((reslove, reject) => {
setTimeout(() => {
reject('async error');
});
});
}
task().catch((e) => console.log(e));
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
注意 promise 内部的错误不会冒泡出来,需要通过 promise.catch 才可以捕获,或者使用
async/await
将异步函数变成同步函数执行,那就可以使用 try/catch 捕获
throw Error
try {
throw new Error('Whoops!');
} catch (e) {
console.error(e.name + ': ' + e.message);
}
1
2
3
4
5
2
3
4
5
堆栈跟踪
using try and catch
using stack
console.log(new Error('custom error').stack);
1
- using console.trace
console.trace(new Error('My Error'));
1
自定义错误类
class ValidationError extends Error {
constructor(message) {
super(message);
// this.name = 'ValidationError'; // 等同于 get name
}
get name() {
return 'ValidationError';
}
}
throw ValidationError('未找到该属性: name');
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
可以使用 instanceof 关键字识别它:
try {
throw ValidationError('未找到该属性: name'); // 抛出 ValidationError 的代码
} catch (e) {
if (e instanceof ValidationError) {
//
}
}
1
2
3
4
5
6
7
2
3
4
5
6
7
使用工具来监控并上报错误
Sentry(https://sentry.io/): 专注于异常(应用崩溃)而不是信息错误。它提供了应用中错误的完整概述,包括受影响的用户数量、调用堆栈、受影响的浏览器以及导致错误的提交等详细信息。
Rollbar(https://rollbar.com/):用于前端、后端和移动应用的无代理错误监控工具。