使用try catch 要注意的地方

try

在平时的开发过程中try catch并不少用, 因此在开发中需要了解和运用它们的使用场景。

基本语法

try {
    //可能会导致错误的代码
} catch (error) {
    //在错误发生时怎么处理
}finally {
     //即使报错始终执行
}
try {
    //可能会导致错误的代码
} catch (error) {
    //在错误发生时怎么处理
}finally {
     //即使报错始终执行
}

如果try块中的任何代码发生了错误,就会立即退出代码执行过程,然后接着执行catch块,此时,catch块会接受到一个包含错误信息的对象。都有一个保存着错误消息的message属性。

当Javascript引擎执行代码是,发生的错误。可能是语法错误,通常是程序员造成的编码错误或者错别字,也可能是来自服务器或者用户的错误输出而导致的错误等。

能被 try catch 捕捉到的异常,必须是在报错的时候,线程执行已经进入 try catch 代码块,且处在 try catch 里面,这个时候才能被捕捉到。

try{
    setTimeout(()=>{
         console.log(a.b);  
    }, 100)
}catch(e){
    console.log('error',e);
}
console.log(111);
// 111
// Uncaught ReferenceError: a is not defined
try{
    setTimeout(()=>{
         console.log(a.b);  
    }, 100)
}catch(e){
    console.log('error',e);
}
console.log(111);
// 111
// Uncaught ReferenceError: a is not defined

setTimeout里面报错,实际是100ms之后执行的代码报错,此时try-catch已经执行完成,console.log都已经被执行完了,所以没有办法捕获到异常。

finally

finally在try-catch语句中是可选的,但是finally子句一经使用,其代码无论如何都会执行。无论try或者catch语句块中包含什么代码,包括return语句,都不会阻止finally子句的执行。

function testFinally(){
    try{
        return 2;
    }catch(error){
        return 1; //
    }finally{
        return 0
    }
}
function testFinally(){
    try{
        return 2;
    }catch(error){
        return 1; //
    }finally{
        return 0
    }
}

从表面上看,这个函数会返回2,执行这个函数且不会报错,但是由于最后还有一个finally子句,结果会导致该return语句忽略,所以这个函数只能返回0。

切记,只要代码中包含finally子句,那么无论try还是catch语句块中的return都将被忽略。所以在使用finally之前,需要想清楚你的代码应该符合你的业务逻辑。

抛出错误

throw操作符,用于随时抛出自定义错误。抛出错误时,必须给throw操作符指定一个值。这个值的类型没有限制。

在遇到throw操作符是,代码会立即停止执行。仅当有try-catch语句捕获到被抛出的值时,代码才能继续执行。

对于浏览器的兼容问,可以高效的定位错误的原因。

function process(values){
    values.sort();
    for(var i = 0; i < values.length; i++){
        if(values[i]>100){
            return values[i];
        }
    }
    return -1;
}
function process(values){
    values.sort();
    for(var i = 0; i < values.length; i++){
        if(values[i]>100){
            return values[i];
        }
    }
    return -1;
}

如果执行process这个函数是,传入的values是一个string,那么调用sort()就会报错,对此,不同的浏览器会给出不同的错误消息,但都不是特别明确;

  • 在IE下:属性或方法不存在
  • 在Firefox下:values.sort()不是一个函数
  • 在Safari下:值undefined不是对象
  • 在Chrome下:对象名没有方法’sort’
  • 在Opera下:类型不匹配 等等

为了兼容方便调试和开发,可以在这个方法中加入一个类型检测

function process1(values){
    if(!(values instanceof Array)){
        throw new Error ("process1(): Argument must be an Array");
    }
    ...
}
function process1(values){
    if(!(values instanceof Array)){
        throw new Error ("process1(): Argument must be an Array");
    }
    ...
}

这样重写函数后,如果values的参数类型不是Array,就会抛出一个错误。

抛出错误与使用try-catch。只应该捕获哪些我们确切地知道该如何处理的错误。捕获错误的目的在于避免浏览器已默认方式处理它们,而抛出错误的目的在于提错误发生的具体原因。

常见的错误类型

错误处理的核心,是首先要知道代码里发生什么错误。错误只会在代码运行期间出现,一般来说,我们需要关注三种错误:

  • 类型转换错误
  • 数据类型错误
  • 通信错误

这些错误分别会在特定的模式下或者没有对值进行足够的检查的情况下发生。