JavaScript 错误处理

错误处理

一、What? 什么是错误处理

错误是指导致系统不能按照用户意图工作的一切原因、事件。在程序设计过程中,由于某些错误的存在,致使程序无法正常运行,处理这些错误以使程序正确运行就称为错误处理。错误处理功能是衡量编译器性能的重要方面,它在帮助程序员尽快修改程序方面起到了非常重要的作用

二、Why? 为什么需要错误处理

程序出现错误,将停止运行,这对于一个后台服务来说是致命的(在服务器上的服务是需要24小时一直运行的)。为了保证程序的健壮性与容错性,即在遇到错误时程序不会崩溃,我们需要对异常进行处理

三、How? 怎么做

(1) try、catch、finally语句

ECMA-262(JS的核心语法标准)的第三版,引入该语法:

try {
    //可能导致错误的代码
}catch(e) { //捕获的错误对象
    //捕获错误之后的处理代码
}finally {
    //执行完所有代码必须做的一些事情,拦截try、catch的结束
}

(2) 语法

1. try不能单独并且要最先出现,其后必须紧跟catch或者finally从句不然语法错误,并且JS不支持多catch从句

可以这么写:

try {

}finally(e) {
    
}

或者:

try {

}catch(e) {
    if(e instanceof ***) { 
        //是这种错误的时候执行什么
    }else if(e instanceof ***) {

    }
}

但是你不能这么写:

try {

}
//OR
catch(e) {

}
//OR
finally{

}

或者:

//java的异常错误处理不能多层catch,只支持一层的catch
try {

}catch(e) {

}catch(e) {

}
2. catch语句的错误对象一定要声明,它属于语法的一部分,即使你不需要,不然发生语法错误

可以这么写:

try {

}catch(errorReason) {//错误对象的参数名可以任意,但是一定要有

}
3. finally的强制打断机制,finally一旦出现,try和catch的return语句会失效

看一段代码:

function getCount(){
    let count = 0
    try {
        count++
        console.log(count, 'try 语句的count')
        return count
        count++
        console.log(count, 'try 语句的count')
    }catch(e) {
        count++
        return count
        count++
        console.log(count, 'catch 语句的count')
    }finally {
        console.log(count, 'finally 语句的count')
        return count
    }
}
const count = getCount()

分析结果 =>

  • 当finally上层的代码(try和catch)按照逻辑执行,但是一旦遇到return,会忽略当前语句块剩余代码,并跳转执行finally的代码
  • 执行finally代码时,如果遇到return语句,当前函数的返回值重新赋值为当前语句表达式结果;如果没有遇到,依然执行完成所以代码,但是返回值为之前的return的表达式的值

四、错误类型

内置错误类型(构造函数):

  • Error 错误基类
  • ReferenceError 引用错误(使用空指针)
  • SyntaError 语法错误
  • TypeError 类型错误 (类型和操作符不匹配,例如不是函数却调用)
  • RangeError 超出范围、内存空间调用超过最大值
  • URLError、EvalError 极少使用,根据名称就知道作用,我就不说明了

对于这些内置的错误类型的实例,浏览器能够对其识别并进行一些处理,当然也有记录错误位置的作用,这使得开发人员易于调试。

Error 语法

通过Error的构造器可以创建一个错误对象。当运行时错误产生时,Error的实例对象会被抛出。Error对象也可用于用户自定义的异常的基础对象

new Error([message[, fileName[,lineNumber]]])
  • message
    可选。可阅读的错误描述信息。
  • fileName
    可选。被创建的Error对象的fileName属性值。默认是调用Error构造器代码所在的文件 的名字。
  • lineNumber
    可选。被创建的Error对象的lineNumber属性值。默认是调用Error构造器代码所在的文件的行号。

Error的prototype上有两个重要的属性:

  • name 错误类型
  • message 错误信息
  • stack 错误栈信息,比message保存的多 => 错误类型、错误信息、错误代码位置(出错所在函数,一直向上直到全局环境)

Error是所以其它内置错误类型的基类

五、抛出错误异常

前面讲了catch(e) 捕获异常语句块,现在我们要讲一讲抛出异常

(1)了解基本

  1. What? 什么是抛出异常
    提示解析器该处语句存在开发者意料之内的异常,希望阻塞停止继续执行代码,以免造成难以弥补的错误。

  2. Why? 为什么需要抛出

    • 抛出异常能比console.log等打印输出函数获得更多的信息提示,便于调试

    • 对一些自定义封装,对于用户来说是透明的,用户的自由度极高,极有可能引发错误,当用户不合理的使用API语法时,抛出错误让用户感知就显得极为重要。例如Vue、React库等都对异常做了很多的处理

  3. How? 怎么抛出
    关键词:throw + 数据(错误原因)
    值得注意的是,数据没有要求是什么类型,只要是一个结果即右值即可。这
    意味着:

    throw ''
    throw 1
    throw true
    throw undefined
    throw null
    throw [1, 2]
    throw function() {console.log('抛出的错误函数')}
    throw {}
    

    这些都是可以的,
    而错误原因一般大家都叫error,因此在try-catch语句一般这么写:

    try {
        let error //error可以是任何的数据类型
        throw error
    }catch(error) { //这个error就是上面代码抛出的error的值
        console.log(error)
    }
    

    catch捕获的错误error就是上面代码抛出的error的值(不考虑代码错误的情况下)

    let error = {a: '1'}
    try {
        throw error
    }catch(e) {
        console.log(e, e === error)//{a: '1'} truw
    }
    
  4. assert,ECMA没有规定,但是可以自己简单实现
    语法:

    function assert (condition, message) {
        if(!condition) {
            throw new Error(message)
        }
    }
    

六、实战应用

  • 函数封装
  • 错误检测
  • 通信异常捕获和传递

(1) 函数封装 和 错误检测

检测参数类型,前面说过直接面对API的开发人员无法知晓内部实现,一旦发生使用错误应该抛出异常,例如

function concat(...strArr) {
    let result = ''
    for(let str of strArr) {
        if(str) {
            result += str
        }
    }
    return result
}

上面函数存在问题就是 if 判断是,发生的类型转换,如果传入的是 0、undefined、null 他们转换为字符串不为空值,这将导致结果与预期不一致。可以做出如下修改:

function concat(...strArr) {
    let result = ''
    for(let [str, index] of strArr.entries()) {
        if(typeof str === 'string') {
            result += str
        }else {
            throw new Error('第' + index + '传入的参数不是string类型')
        }
    }
    return result
}

确保连接的只是字符串

(2) 通信异常捕获和传递 <=> ajax + promise => axios

try {
    $.ajax({...config})
}catch(error) {
    console.log(error) // 网络资源请求错误
}

七、总结

在实际的开发中最好定义自己的错误类型,主要代码更加健壮,其次便于调试

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值