不要在代码中随便使用try...catch了

2024-03-20 1085阅读

温馨提示:这篇文章已超过368天没有更新,请注意相关的内容是否还可用!

前言

 📫 大家好,我是南木元元,热爱技术和分享,欢迎大家交流,一起学习进步!

 🍅 个人主页:南木元元


目录

背景

js中的try...catch

try...catch运行机制

js的事件循环机制

try...catch无法捕获异步错误的原因

解决方法

结语


背景

之前面某物的时候,遇到了一个有关try...catch的问题,让我印象深刻,这里来记录分享一下。

面试官:下面代码有什么问题吗?

示例1:

try {
  setTimeout(() => {
    throw new Error('err');
  }, 200);
} catch (err) {
  console.log(err);
}

示例2:

try {
  Promise.resolve().then(() => {
    throw new Error('err');
  });
} catch (err) {
  console.log(err);
}

不要在代码中随便使用try...catch了

第一反应是,这不就是一个普通的try...catch捕获错误吗?但其实是有坑在里面的。

js中的try...catch

js中的try...catch是平时写代码时经常会使用的,它可以捕获代码中的异常并防止应用程序崩溃。

try {
  // 可能会抛出异常的代码
} catch(error) {
  // 处理所有异常的代码
}

但try...catch并不能捕获所有的异常,这就需要了解try...catch的运行机制,这样才能保证我们合理地去使用它。

try...catch运行机制

当程序运行到try...catch里面时:

  • 如果未报错,则会忽略catch中的代码
  • 若报错,则不执行try报错内容后面的代码,转而执行catch中的代码

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

    js的事件循环机制

    js是单线程语言,事件循环是js的执行机制。

    1. 所有同步任务都在主线程上执行,形成一个执行栈
    2. 在执行同步任务的时候,如果遇到了异步事件,会将该任务挂起,继续执行同步任务,当异步事件执行完后(如定时器到时,ajax请求返回),再将对应的回调加入到一个任务队列中等待执行,任务队列可以分为宏任务队列和微任务队列
    3. 当执行栈中的同步任务执行完毕后,会执行所有微任务,清空微任务队列
    4. 当执行完所有微任务后,再去执行宏任务队列中的下一个宏任务,不断循环,直到所有任务都完成。

    这一套流程,就是事件循环。

    不要在代码中随便使用try...catch了

    错误原因

    现在回到上述代码,其实就能够明白存在的问题是try...catch无法捕获异步错误。

    try...catch是同步执行的,而setTimeout和Promise.resolve()一个是宏任务,一个是微任务,都是异步任务,等到setTimeout和Promise.resolve()里面的事件进入到事件队列的时候,主线程已经离开了try...catch,所以try...catch无法捕获异步错误。

    解决方法

    只需在同步任务中使用try...catch即可,利用Promise和async/await的内在能力。

    对于第一个示例:

    new Promise((resolve, reject) => {
      setTimeout(() => {
        try {
          throw new Error('err');
        } catch (err) {
          reject(err);
        }
      }, 200); 
    })
    .then(() => {
      // 处理成功执行的情况
    })
    .catch((err) => {
      console.log(err); // 错误在这里被捕获
    });

    对于第二个示例:

    // 方法一:使用Promise链式调用
    Promise.resolve()
      .then(() => {
        throw new Error('err');
      })
      .catch((err) => {
        console.log(err); // 错误在这里被捕获
      });
    // 方法二:使用async/await
    async function handleError() {
      try {
        await Promise.resolve().then(() => {
          throw new Error('err');
        });
      } catch (err) {
        console.log(err); // 错误在这里被捕获
      }
    }
    handleError();

    结语

    因此,在代码中不要再随便写try...catch了,异步错误是无法被捕获的,而且像Promise有它自己的异常捕获方法,比try...catch更好用。

    🔥如果此文对你有帮助的话,欢迎💗关注、👍点赞、⭐收藏、✍️评论,支持一下博主~ 

VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]