trycatch 不能捕获运行时异常_面试官:用一句话描述 JS 异常是否能被 try catch 捕获到 ?...

关于trycatch的运行机制

当程序运行到try catch里面时,如果未报错,则忽略catch中的代码,若报错,则不执行try报错内容后面的代码,转而执行catch中的代码。

什么时候try catch 才能捕获到异常?

能捕捉到的异常必须是线程执行已经进入 try catch 但 try catch 未执行完的时候抛出来的

1,当语法错误时,不能捕获

因为语法错误是在语法检查阶段就报错了,线程执行尚未进入 try catch 代码块,自然就无法捕获到异常。 例如:

try{
    a.
}catch(e){
    console.log("error",e);
}
// output
Uncaught SyntaxError: Unexpected token '}'
复制代码

image.png

2,语法正确,线程进入try catch中时,可以捕获

function d(){a.b;}
try{
   d();
}catch(e){
     console.log("error",e);
}
// output
error ReferenceError: a is not defined
复制代码

image.png

代码执行进入了 try catch ,执行 d() 方法的时候,线程执行处在 try 里面,所以能捕捉到。

3,异步无法捕获

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

image.png

因为,setTimeout是异步函数,而try catch其实是同步顺序执行的代码,等setTimeout里面的事件进入事件队列的时候,主线程已经离开了try catch,所以try catch是无法捕获异步函数的错误的。

4.Promise异常无法捕获

// 异步,微任务
try {
	new Promise(() => {
		throw new Error('new promise throw error');
	});
} catch (error) {
	console.log(error);
}
复制代码

image.png

try-catch 主要用于捕获异常,注意,这里的异常,是指同步函数的异常,如果 try 里面的异步方法出现了异常,此时catch 是无法捕获到异常的,原因是因为:当异步函数抛出异常时,对于宏任务而言,执行函数时已经将该函数推入栈,此时并不在 try-catch 所在的栈,所以 try-catch 并不能捕获到错误。对于微任务而言,比如 promise,promise 的构造函数的异常只能被自带的 reject 也就是.catch 函数捕获到。

如果想要捕获Promise异常

  • 1.Promise异常并不是绝对不能被捕获到的,如下
async function fn() {
    try {
        await new Promise(() => {
            throw new Error('new promise throw error');
        });
    } catch (error) {
        console.log(error);
    }
}
fn()
复制代码

代码运行结果

image.png

这次Promise异常能被捕获到,是因为async和await,正常不加async,await的时候,执行promise后,在等待promise回调的时候,try,catch已经执行完了,所以捕获不到,然而加了async和await后,try,catch必须等promise的回调执行完后,才能继续往下走,这个时候trycatch没执行完,promise抛出异常,自然而然能被catch捕获到

  • 2.关于promise异常到底是被catch捕获还是.catch捕获

接下来我们把代码修改一下

async function fn() {
    try {
        await new Promise(() => {
            throw new Error('new promise throw error');
        }).catch(error=>{
            console.log('.catch',error);
        })
    } catch (error) {
        console.log('try,catch',error);
    }
}
fn()
复制代码

.catch大家都知道,用来捕获promise异常,当我们有了.catch,错误在进入catch之前,就被.catch捕获到了,所以不会再往下走(可能有点绕,.catch是Promise异常捕获机制,不带. 是try,catch) 代码运行结果如下

image.png

到这里,我们可以发现,这个错误被.catch捕获到了,那如果我们不抛出一个错误,直接返回一个reject 会怎么样呢

async function fn() {
    try {
        const res = await new Promise((resove,reject) => {
            return reject('捕获到了')
        }).catch(error=>{
            console.log('被promise.catch',error);
        })
    } catch (error) {
        console.log('被try,catch',error);
    }
}
fn()
复制代码

运行结果

image.png

Promise异常,如果写了.catch,就会被优先.catch捕获到,如果没有,那么就会被try,catch捕获到,

总结

通过上面分析,我们得出能被 try catch 捕捉到的异常,必须是在报错的时候,线程执行已经进入 try catch 代码块,且处在 try catch 里面,这个时候才能被捕捉到。 并且,try,catch如果使用async和await,也是可以捕获到Promise异常的,但我们不推荐,毕竟,Promise异常有它自己的.catch来捕获,而且更好用,不是吗?


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值