@JunQiu
2018-09-18T20:57:42.000000Z
字数 3332
阅读 1121
summary_2018/07
language_js
think
### 自定义错误
function UserError(message) {
this.message = message || '默认信息';
this.name = 'UserError';
}
// 继承Error对象
UserError.prototype = new Error();
UserError.prototype.constructor = UserError;
### 异常的处理try_catch_finally/throw
##throw语句的作用是手动中断程序执行,抛出一个错误。
## try_catch
1、一旦发生错误,程序就中止执行了,不再往下执行。JavaScript 提供了try...catch结构,允许对错误进行处理,选择是否往下执行。
2、一旦捕获错误,JavaScript引擎就立即把代码的执行转到catch代码块,不再只想try中的语句
try {
throw new Error('出错了!');
} catch (e) {
console.log(e.name + ": " + e.message);
console.log(e.stack);
}
// 对不同类型的错误进行处理
try {
foo.bar();
} catch (e) {
if (e instanceof EvalError) {
console.log(e.name + ": " + e.message);
} else if (e instanceof RangeError) {
console.log(e.name + ": " + e.message);
}
// ...
}
## finally
try...catch结构允许在最后添加一个finally代码块,表示不管是否出现错误,都必需在最后运行的语句。
!!!Tips:return语句的执行是排在finally代码之前,只是等finally代码执行完毕后才返回。
var count = 0;
function countUp() {
try {
return count;
} finally {
count++;
}
}
countUp() // 0
但是finally语句块中的return可能会覆盖,catch中的return
function f() {
try {
console.log(0);
throw 'bug';
} catch(e) {
console.log(1);
return true; // 这句原本会延迟到 finally 代码块结束再执行
console.log(2); // 不会运行
} finally {
console.log(3);
return false; // 这句会覆盖掉前面那句 return
console.log(4); // 不会运行
}
console.log(5); // 不会运行
}
var result = f();
0
1
3
false
## 前言
在业务开发中,必然会遇到异常或错误,良好的异常/错误处理能够使代码的结构更加清晰,处理更加清晰,提高项目的健壮行。
## 当遇到异常/错误的时候是否需要进行处理
我们可能遇到不一样的错误,有可修复的,不可修复的,或者需要返回给用户,其实感觉这是一个比较复杂的情况,因为在不同的任务,我们可能根据项目的实际情况有不同的处理方式,比如:
1、一些可以修复的已知的错误/异常,比如输入的类型需要的是number,输入的是字符串,我们可以在Catch中进行处理,使程序正常运行,并记录日志
2、不可修复的错误:
(1)需要结束资源(如数据库连接),我们可以使用finaly来完成。
(2)需要给用户返回信息,可以捕获错误/异常后,结束任务,或者抛给上层进行处理,但都需要返回用户相关错误信息
(3)不需要处理类型,让系统/服务器自己处理
## 关于错误/异常处理的一些建议
1、良好的使用自定义错误,当原始的错误类型不能描述产生的错误时,最好使用自定义错误来更加清楚的描述所产生的错误
2、永远不要吞下异常
当捕获异常时,必须进行处理,而不是吞下错误,那样会导致任务失败的原因,可以使用日志记录,或者抛出错误给使用者
try {
}catch (e) {
logger.../throw err
}
3、捕获错误或者异常时,最好捕获特定的类型,使错误或异常描述更加清晰
4、始终完整的返回异常,以便完整的返回错误,便于追踪错误原因,比如在抛出异常时
try {
throw new Error()
}catch (Error) {
//错误
throw new Error(Error.message)
//正确
throw new Error(Error)
}
5、记录异常/错误或者抛出它们,但不同时执行
同时抛出和记录异常/错误会导致日志中出现重复的错误记录,不便于日志的分析
6、永远不要在finally块中抛出异常,记录日志
finally的设计细想我认为在于处理一些因为异常/无异常情况下的收尾工作,比如资源的清理
try {
}catch (Error) {
}finally {
//数据库、网络连接、其他资源的一些关闭
}
7、请记住返回占用的资源。如果不打算处理异常,可以使用try_finally做最后的资源清理
try {
}finally {
//数据库、网络连接、其他资源的一些关闭
}
8、尽早的捕获错误/异常可以尽早处理,或者退出程序的执行
比如:
1)验证用户
2)插入用户
3)验证地址
4)插入地址
5)如果出现问题则回滚所有内容
1)验证用户
2)验证地址
3)插入用户
4)插入地址
5)如果出现问题则回滚所有内容
9、始终在单个日志消息中包含有关异常的所有信息
LOGGER.debug("Using cache sector A");
LOGGER.debug("Using retry sector B");
虽然在日志比较少的地方可能并不能看出来,但在没秒几十万条时,两条日志消息的距离可能相差几百条,十分难找到,不利于排查错误。
10、使用模版方法来处理异常/错误,减少代码的冗余
try {
} catch (e)
//处理异常的方法
dealException(e)
}