什么时候应该在JavaScript中使用try/catch ?

When should you use try/catch in JavaScript?

本文关键字:try catch JavaScript 什么时候      更新时间:2023-09-26

当我用JavaScript开发正常的web应用程序时,通常不需要try/catch语句。JavaScript中没有检查异常,文件IO或数据库连接。

try/catch语句在JavaScript中有用吗?我什么时候可以使用它?

try...catch块通常被鼓励较少使用,这并不取决于您使用的语言。

主要原因是catch块的成本。另一个原因是,当你用单个try...catch块包装许多语句时,在catch块中,你无法确定主要问题到底是什么。

最好使用输入验证或if...else块之类的技术来减少发生异常(错误)的概率。例如,当您想处理从user获取的数字时,您可以使用:

而不是使用try...catch,您可以使用:
if (isNaN(numberVariable))
{
    alert('you should enter a valid number');
}

我发现try/catch/finally很有用的一个场景是在深度嵌套的对象中,null可以在任何级别弹出。例如,考虑如下:

var something = one.two.three.four.five;

要100%安全地执行这个"get",必须编写一些冗长的代码:

if(one && one.two && one.two.three && one.two.three.four)
   something = one.two.three.four.five;

现在想象一下变量名是真实的并且很长,你很快就会得到一个非常难看的if语句。

我倾向于使用try/catch/finally来简化这一点,当我不关心任何"else"场景,只是想要对象或不:

var something;
try { something = one.two.three.four.five; }
catch { something = "default"; }
finally { doSomething(something); }

我从这里的一个帖子中发现了这个:

何时应该使用try-catch?

try-catch语句应该在任何时候使用,当您想要对用户隐藏错误时,或者当您想要为用户产生自定义错误时。如果你还没有弄清楚,当你执行try-catch语句时,浏览器通常的错误处理机制将被禁用。

在构建大型应用程序时,您可能会看到这样做的好处。调试任何应用程序流中的每种可能情况通常都很耗时,而且许多可能性可能会被无意中忽略。当然,通过适当的bug测试,没有任何地方可以被忽视。但是try-catch语句在你的代码中可以作为一个很好的回退,在开发过程中没有预见到的异常情况下可能会失败。

try-catch语句提供的另一个好处是,它向用户隐藏了过于技术性的错误消息,而用户无论如何也无法理解这些消息。

使用try-catch的最佳时机是在代码的某些部分,在这些部分,无论出于何种原因,您怀疑会发生超出您控制范围的错误。

何时应该避免try-catch ?

如果您知道将要发生错误,就不应该使用try-catch语句,因为在这种情况下,您会想要调试问题,而不是屏蔽它。try-catch语句应该只在您怀疑可能发生错误的代码段上执行,并且由于可能出现的情况太多,您无法完全验证是否会发生错误,或者何时会发生错误。在后一种情况下,使用try-catch是适当的。

在运行的代码可能抛出异常时使用它。请记住,您可以对自己的错误进行throw—我使用的大多数try…catch工具都是用于捕获我自己的异常。

外部Javascript库和小部件经常使用异常来处理实例化错误。通常需要:

try {
  var w = new Widget();
}
catch (e) {
  // widget failed
}

我不同意使用try…JavaScript中的catch:

var something;
try { something = one.two.three.four.five; }
catch { something = "default"; }
finally { doSomething(something); }
https://stackoverflow.com/a/26172702/12410906

因为在读取对象的Prop之前记住条件是否存在是属于JavaScript知识的东西。你不能假装你不知道它,只是写一个深prop读取链和包装一个尝试…抓住它。这就像如果你调用像函数这样的原始值也会触发异常:

const val = 1
val()

你不能假装不知道,然后放弃尝试…在每次函数调用时捕获。我同意在JavaScript中读取prop时很容易忘记对象是否存在的条件,但这是因为JavaScript的设计错误(typescript用可选的链操作符解决了这个问题),总之,这不是一个很好的例子来显示何时使用try…catch。

要了解何时使用try…Catch需要知道何时首先抛出错误。

何时抛出错误

一个错误是当一些非常糟糕的事情发生时,生产者抛出给消费者的东西,使得生产者不得不停止,直到消费者(在大多数情况下)做出改变。

例如,如果后端API是生产者,前端代码可能是消费者。当前端请求后端没有的东西时,后端无法继续,因此它会向前端抛出404错误;当前端请求一些未经验证的保护时,后端会抛出401错误来强制前端输入用户名和密码;当服务器硬盘爆炸时,会抛出另一种形式的错误(如果服务器仍然可以运行)。

前端代码也可以是前端代码的消费者。例如,您正在使用jQuery库,jQuery将成为生产者,而您的前端代码将成为消费者。这是jQuery抛出错误的源代码示例:

// from jQuery source code
        function( w ) {
            if ( !w.document ) {
                throw new Error( "jQuery requires a window with a document" );
            }
            return factory( w );
        };

看,前端开发人员(消费者)在甚至不存在文档的环境中使用jQuery,所以jQuery(生产者)真的不能继续抛出错误并停止一切,直到开发人员做对了。

如果你正在开发一个web应用程序,浏览你的web应用程序的用户将是消费者,那么你的web应用程序代码将是生产者。肯定会有一些糟糕的事情发生,比如用户可能会请求一个不存在的url(假设在spa应用程序中),或者用户可能会在手机号码输入中输入英文字母,如果你只是简单地抛出一个错误,就像jQuery, Vue,后端会做的那样,用户(消费者)无法捕获它并消费它。

你真正应该做的是显示一些吐司或导航到一个特殊的404路由,让用户知道发生了什么。这就是为什么我们大多数前端开发人员很少抛出错误。

何时尝试…catch

在理解了何时抛出错误之后,这个问题就容易了。如果您正在使用可能抛出错误的生产者,您可以尝试…抓住它,这是来自vue-next: 的一段源代码
// from vue-next source code
 try {
    result = postcss(plugins).process(source, postCSSOptions)
    ...
   }catch(e){}

它尝试的原因是…Catch是因为插件postcss会在输入不正确时抛出错误。或者尝试JSON。解析来自服务器的字符串,你尝试…抓住它。这是一个普遍的原则。

我个人(错误地)使用它,当我编写一些我不确定是否能正确执行的代码时,但用户不需要知道错误。

除此之外,我一直在一些用户控件上使用它,你可以在你的HTML标记中定义一个'action'属性,javascript将尝试执行该操作,像这样:

try{
     window['method'](args);
}catch(e){
     try{
         window['optionalExceptionHandler'](e, args);
     }catch(e){ return; }
}

(我喜欢认为它比eval() xD更好)