错误处理try catch
捕获异步
setTimeout(() => {try{// do some} catch (err) {// 这里捕获}}, 1000)
抛出自定义错误throw
let json = '{ "age": 30 }'; // 不完整的数据try {let user = JSON.parse(json); // <-- 没有 errorif (!user.name) {throw new SyntaxError("Incomplete data: no name"); // (*)}alert( user.name );} catch(e) {alert( "JSON Error: " + e.message ); // JSON Error: Incomplete data: no name}
再次抛出
预料之外的错误,catch中不止如处理,则可以再次抛出。
此时,更外层的 try catch 将捕获到错误,但如果外部不存在这种结构,脚本就会被杀死。
try catch finally
* finally和return
控制转向外部之前 finally 先执行
function func() {try {return 1;} catch (e) {//...} finally {alert('finally')}}alert(func()); // 先执行finally中的alert,再执行alert 1
全局catch
window.onerror = function(message, url, line, col, error) {}// nodeprocess.on("uncaughtException")
自定义Error
扩展自Error
Error类的内部实现大致是:
class Error {constructor(message) {this.message = messagethis.name = 'Error' // 不同Error类,比如SyntaxError就是this.name = 'SyntaxError'this.stack = <call stack> // 调用栈信息}}
所以我们可以继承,重写name。
class MyError extends Error {constructor(message) {super(message)this.name = 'MyError'}}const myErr = new MyError('我的自定义错误')myErr.name = 'MyError'
通过 intanceof 操作符,可以判断错误是否是你的自定义错误,从而来做特殊的处理。如果不确定的错误,则应再次抛出。
if(err instanceof MyError) {// ... do some} else {// 再次抛出,在try catch里说过。throw err}
深入继承
这里举个例子,访问对象的某个属性的错误处理。
class ValidationError extends Error {constructor(msg) {super(msg)this.name = 'validationError'}}class PropertyRequiredError extends ValidatationError {constructor(property) {// 使用方便,只需要new PropertyRequiredError('属性名')即可,报错message由super,也就是Error的constructor函数来做this.message = messagesuper('no property: ' + property)this.name = 'PropertyRequiredError'}}// read some jsonif(!user.name) {throw new PropertyRequiredError('name')}
我们在每个自定义的Error类中都重写了name,这步可以简写为
// 一个自定义的Error父类,其他自定义Error类继承自该父类。// 因为我们无法重写Error内建类class MyError extends Error {constructor(msg) {super(msg)// 使用当前调用构造函数名this.name = this.constructor.name}}class ValidationError extends MyError {}new ValidationError() // this.name = ValidationError
