try...catch错误捕获

2,936 阅读2分钟

这是我参与8月更文挑战的第7天,活动详情查看: 8月更文挑战

前言

最近写快应用,有个数据格式转化的问题。为了防止后端数据出错,就加了个try...catch来错误捕获。结果发现有些情况明明数据出问题了,却没有将异常抛出来,后来仔细分析了下,原来因为代码在报错的时候,try...catch已经执行完了。这篇文章就来整理下try...catch的具体用法。

try...catch

首先来看下try...catch的作用:

try...catch能捕获的异常必须是线程执行进入到try...catch且try...catch未执行完的时候抛出来。

1. 进入之前

语法异常在语法检查阶段就报错了,线程尚未进入try...catch代码块,所以无法捕获到异常。

try {
    a.
}catch(e) {
    console.log('error-------', e);
}

// 执行结果:
VM483:3 Uncaught SyntaxError: Unexpected token '}'

2. 进入之中

代码报错的时候,线程处于try...catch之中,能够捕获到异常。

try {
    a.b
}catch(e) {
    console.log('error-------', e);
}

VM488:4 error------- ReferenceError: a is not defined

3. 进入之后

代码报错的时候,线程已经执行完try...catch,这种无法捕获异常。

try {
    setTimeout(() => {
        a.b = 1;
    }, 1000)
}catch(e) {
    console.log('error---------', e);
}


// 执行结果:
VM544:3 Uncaught ReferenceError: a is not defined

try...catch无法捕获异步代码中抛出的错误,如果要捕获则应该将try...catch代码写到异步代码内部。

setTimeout(() => {
    try{
        a.b = 1;
    }catch(e) {
        console.log('error---------', e);
    }
}, 1000)

// 执行结果:
error--------- ReferenceError: a is not defined at <anonymous>:3:9

4. Promise的异常

线程在执行a.b的时候,try...catch也在同步执行。为啥也没捕获到异常??

Promise在执行的时候,函数代码周围都是有个隐式的try...catch包裹的,所有的同步异常都会被内部捕获到,但是并不会往上抛异常。所以我们写的try...catch并不会捕获到。

try{
    new Promise(function (resolve, reject) {
        a.b;
    }).then(v=>{
        console.log(v);
    });
}catch(e){
    console.log('error---------------',e);
}


// 执行结果:
Promise {<rejected>: ReferenceError: a is not defined
    at <anonymous>:3:9
    at new Promise (<anonymous>)
    at <an…}__proto__: Promise[[PromiseState]]: "rejected"[[PromiseResult]]: ReferenceError: a is not defined
    at <anonymous>:3:9
    at new Promise (<anonymous>)
    at <anonymous>:2:5
    
VM552:3 Uncaught (in promise) ReferenceError: a is not defined
    at <anonymous>:3:9

5. async...await异常

如何用try...catch去捕获async...await的错误呢??

是不是像Promise那样直接写在async最外层??

try{
    async function f1() {
        await Promise.reject(new Error('await错误'));
    }
    f1();
}catch(e) {
    console.log(111, e)
}

结果:

image.png

将try...catch写在async函数最外层并不能捕获async...await的异常,而是会走到Promise的异常抛出。

那如果将try...catch写在await呢??

async function f2() {
    try{
        await Promise.reject(new Error('await出错'));
    }catch(e) {
        console.log(111, e);
    }
}
f2();

//执行结果:
111 Error: await出错 at f2 (<anonymous>:3:30)

async...await捕获异常,需要将await函数写在try...catch中。