【问题标题】:When should you use try/catch in JavaScript?什么时候应该在 JavaScript 中使用 try/catch?
【发布时间】:2011-11-01 03:48:25
【问题描述】:

当我使用 JavaScript 开发普通的 Web 应用程序时,通常不需要 try/catch 语句。 JavaScript 中没有checked exception、文件 IO 或数据库连接。

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

【问题讨论】:

  • 'JavaScript 中没有文件 IO 或数据库连接。' Node.js 实际上支持这些,虽然它不需要你使用try/catch

标签: javascript try-catch


【解决方案1】:

我不同意这是在 JavaScript 中使用 try...catch 的好场景:

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

https://stackoverflow.com/a/26172702/12410906

因为在读取它的 Prop 之前记住条件对象是否存在是属于 JavaScript 知识的东西。你不能假装你不知道它,只是写一个深的道具阅读链并包装一个 try...catch 。就好像你调用一个函数之类的原始值也会触发异常:

const val = 1
val()

你不能假装你不知道它并包装一个 try...catch 每个函数调用。我同意在 JavaScript 中读取 prop 时如果对象存在很容易忘记条件,但那是因为 javascript 的设计错误(打字稿使用可选链接运算符解决了这个问题),总之,这不是一个很好的例子来说明何时使用 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(生产者)真的不能继续抛出错误并停止一切,直到开发者做对了。

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

您真正要做的是展示一些 toast 或导航到特殊的 404 路线,让用户知道发生了什么。这就是我们大多数前端开发人员很少抛出错误的原因。

何时尝试...赶上

在了解了何时抛出错误之后,这个问题就很容易了。如果你正在消费一个可能会抛出错误的生产者,你尝试......抓住它,这是一段来自 vue-next 的源代码:

// from vue-next source code

 try {
    result = postcss(plugins).process(source, postCSSOptions)
    ...
   }catch(e){}

之所以 try...catch 是因为插件 postcss 在输入不正确时会抛出错误。或者您尝试 JSON.parse 来自服务器的字符串,您尝试...捕获它。这是一般原则。

【讨论】:

    【解决方案2】:

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

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

    最好使用输入验证或if...else 块等技术来降低发生异常(错误)的可能性。例如,当您想使用取自用户的数字时,您可以使用:

    if (isNaN(numberVariable))
    {
        alert('you should enter a valid number');
    }
    

    【讨论】:

      【解决方案3】:

      我是从post here 找到的:

      什么时候应该使用 try-catch?

      当您想要向用户隐藏错误时,或者您想要为用户的利益生成自定义错误时,都应该使用 try-catch 语句。如果你还没弄明白,当你执行 try-catch 语句时,浏览器通常的错误处理机制就会被禁用。

      在构建大型应用程序时,您可能会看到这样做可能带来的好处。调试任何应用程序流程中的所有可能情况通常很耗时,并且可能会无意中忽略许多可能性。当然,通过适当的错误测试,任何区域都不应被忽视。但是 try-catch 语句在开发过程中未预见到的异常情况下可能会失败的代码区域中作为一个很好的后备。

      try-catch 语句提供的另一个好处是,它可以向那些无论如何也不会理解的用户隐藏技术性过强的错误消息。

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

      什么时候应该避免 try-catch?

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

      【讨论】:

      • 投了反对票,因为您刚刚从impressivewebs.com/javascript-try-catch复制了答案
      • @FarazKelhini 我没有说这是我的答案,我已经提到了答案的来源!
      • 哦,我的错。我没看到链接。我会赞成你的答案,但stackoverflow不允许我在两天后改变我的投票,除非你编辑你的答案!这是荒唐的。再次抱歉。
      • @FarazKelhini 别担心。我不太关心选票。编码愉快!
      【解决方案4】:

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

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

      要以 100% 的安全性执行此“获取”,必须编写一些冗长的代码:

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

      现在假设变量名是真实的并且更长,你很快就会得到一个非常丑陋的代码 if 语句。

      当我不关心任何“其他”场景并且只想要对象时,我倾向于使用 try/catch/finally 来简化它:

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

      【讨论】:

      • 周到的回答。
      • 如果您可以使用Lodash 库,get 方法对此非常有帮助。例如。 _.get(myObject, 'one.two.three.four.five').
      • @parliament 仍然有效。由于某种原因您无权访问其他库,那么此解决方案可能是唯一的选择。此外,如果您只需要查看 2 或 3 个级别的深度,那么为此添加一个库可能是多余的。
      • @parliament 很有趣,你说你现在对此感到畏缩,因为我最初的反应是“哇,这真是天才”。但现在你可以只使用可选链(我在 coffeescript 中喜欢的东西之一)。 let something = one?.two?.three?.four?.five; 几乎完全支持,但很容易被 babel 支持
      • 啊,是的,忘了可选链! Typescript 3.7 typescriptlang.org/docs/handbook/release-notes/… 也支持。
      【解决方案5】:

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

      除此之外,我一直在一些用户控件上使用它,您可以在 HTML 标记中定义一个“动作”属性,然后 javascript 将尝试执行该动作,如下所示:

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

      (我觉得比eval()xD好)

      【讨论】:

        【解决方案6】:

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

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

        【讨论】:

          【解决方案7】:

          在您运行的代码可能引发异常时使用它。请记住,您可以throw 自己的错误——我使用的大部分try…catch 东西都是为了捕获我自己的异常。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-12-03
            • 2021-05-02
            • 1970-01-01
            • 2018-06-20
            • 1970-01-01
            • 2013-06-16
            相关资源
            最近更新 更多