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

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

关于写这篇博客的原因,是因为最近在工作中用try,catch捕获Promise错误时,有的时候捕获不到,有的时候又被promise.catch捕获,对其捕获机制和顺序并不是很明白,查阅了很多资料,也没有写的很透彻的资料,所以写篇博客,方便日后查阅

前言

平常撸代码的时候,try catch 用的太多了,特别是一些 ”安全感" 低的人,基本是到处 try catch,生怕 JS 报错,然后页面整个挂掉了。

为什么安全感低呢,因为界限模糊,很多新手前端不知道try,catch捕获的是哪种异常,而且能否捕获Promise异常,以及如果Promise用.catch捕获,到底被谁捕获到

所以我们要弄清楚try catch,做一个安全感高的码农!!!

  • 面试官:麻烦用一句话描述 JS 异常是否能被 try catch 到?

  • 面试者:异步方法无法捕捉到……

  • 面试官:不要背答案,麻烦用一句话描述 JS 异常是否能被 try catch 到!

  • 面试者:沉默 ing …………

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

  • 面试官:沉默 ing …………

  • 面试官:啥时候可以来上班?

  • 欢笑交谈中,拿到 offer …………

u=289018151,172936710&fm=26&fmt=auto.webp

关于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来捕获,而且更好用,不是吗?

所以,没安全感的兄弟们,看完这篇文章,不要再到处写trycatch了,我们自己写的代码,没我们想的这么脆弱

如果上述文章有哪里不对或需要改进,可以再底下评论或私信,一起学习交流

编辑不易,个位看官老爷,点个赞呗!!!!!!

参考文献

分类:
前端
分类:
前端
收藏成功!
已添加到「」, 点击更改