【问题标题】:JavaScript try/catch: errors or exceptions?JavaScript try/catch:错误还是异常?
【发布时间】:2011-02-04 22:47:18
【问题描述】:

好的。我可能在这里分裂头发,但我的代码不一致,我想这样做。但在我这样做之前,我想确保我走的是正确的道路。实际上这并不重要,但这一直困扰着我一段时间,所以我想我会问我的同龄人......

每次我使用 try... catch 语句时,我总是在 catch 块中将一条消息记录到我的内部控制台。但是我的日志消息并不一致。它们看起来像:

catch(err) {
DFTools.console.log("someMethod caught an error: ",err.message);
...

或:

catch(ex) {
DFTools.console.log("someMethod caught an exception: ",ex.message);
...

显然,无论哪种方式,代码都能正常运行,但我开始感到困扰的是,我有时会提到“错误”,有时会提到“异常”。就像我说的那样,也许我正在分裂头发,但哪个是正确的术语? “异常”还是“错误”?

【问题讨论】:

  • 我一直把它称为“异常处理”,但是要触发一个catch块你throw new Error("..."),所以...
  • 好吧,你可以扔任何你想要的东西 - throw "Hi Mom!"; 是完全有效的。
  • 是的。也许我应该说 I 抛出新的 Error 对象,或者继承自 Error 的对象。

标签: javascript error-handling nomenclature


【解决方案1】:

主要免责声明:我认为对此没有“正确”的答案。这里表达的观点是主观的和个人的。更重要的是,我将要支持的想法只有在你打算用不同的、咳咳、错误的方式做不同的事情时才有用……因为你可能会根据 Daniel Earwicker 的信息性回答使用系统。考虑到这一点:

我认为“例外是例外”。 ERROR 不太出人意料。

免责声明:以下伪代码不好;它只是作为我能想到的最小例子来说明我的观点。

注意:在这个思想实验中,GetFile如果找不到指定的文件则返回UNDEFINED。

function AlwaysGetFile(name){
    var file = null;
    if(FileExists(name)){
        file = GetFile(name);
        if(typeof file === "undefined"){
            throw new "couldn't retrieve file" EXCEPTION
        }
    }
    else{
        throw new "file does not exist" ERROR
    }
    return file;
}

如果消费者使用不存在的文件名调用 GetFileOrThrow,则会发生错误。在我看来,区别实际上是更高级别的代码(或用户输入)做错了什么......这个函数必须将一个错误传递给可以决定如何处理这个结果的更高级别的代码。像这样考虑......这个函数会对任何消费函数说:

听着,我的朋友,我知道这里发生了什么:请求 BobAccounts.xml 是一个错误,所以不要再这样做了!哦,如果你认为你现在知道出了什么问题(虐待了我),那就继续努力吧!

现在考虑这种情况,这个函数使用名称,检查文件是否存在,然后由于某种原因无法检索它。这是一个不同的情况。确实发生了意想不到的事情。更重要的是,消费代码不应该受到责备。现在我们真的希望这个函数对任何消费函数说:

哦,提琴手!对此感到抱歉,我谦虚地请求您的原谅,但是我不太明白的一些特别的事情出了问题。我不认为您对 BobAccounts.xml 的请求是不合理的......而且我知道我应该为您完成它。由于我的代码级别比你低,我真的应该知道发生了什么……但我不知道……而且由于你理解这种特殊情况的机会比我少,我想你可能会最好停止你正在做的事情,让这条消息一直到顶部......我的意思是,这里有一些严重可疑的事情发生。

所以我想我的总结是这样的:如果错误发生在高阶代码中(你传递了错误的数据)抛出一个错误。如果错误发生在低阶代码中(您依赖的函数以您不理解且无法计划的方式失败)抛出异常......并且如果错误发生在您当前正在编写的函数中...... . 好吧,呃,如果你知道它,那就修复它!

最后,更直接地回答最初的问题:在处理错误和异常方面,我的建议是:优雅地处理所有错误(可选地记录它们)......但确实要小心处理异常;仅当您确定自己知道异常是什么以及为什么会发生时,才尝试从异常中恢复,否则让它冒泡(如果必须重新抛出它)。

【讨论】:

    【解决方案2】:

    ECMAScript specification 称它们为异常。您可能也想这样做。

    为了让您的日志记录更加丰富:

    catch(ex) {
        DFTools.console.log("someMethod caught an exception of type " 
           + ex.name + ": ", ex.message);
    

    您可能还需要记住,异常(很遗憾)可以是任何类型,因此不一定具有 namemessage 属性:

    catch(ex) {
        if (ex.message && ex.name) {        
            DFTools.console.log("someMethod caught an exception of type " 
               + ex.name + ": ", ex.message);
        } else /* deal with it somehow */
    

    由于到处重复这看起来很麻烦,您可能希望在函数中捕获它:

    function logExceptions(methodName, action) {
    
        try {
    
            action();
    
        } catch (ex) {
            if (ex.message && ex.name) {        
                DFTools.console.log("someMethod caught an exception of type " 
                   + ex.name + ": ", ex.message);
            } else {
                DFTools.console.log("someMethod caught a poorly-typed exception: " + ex);
            }
        }
    }
    

    现在你可以说:

    logExceptions(function() {
    
        // do some risky stuff...
    
    });
    

    【讨论】:

    • 哈!实际上,ECMAScript 规范称为“错误异常”!
    • 是的,所有标准的异常构造函数都使用 Error 而不是 Exception... 但那是 JS 给你的! :) 但这可能是因为那些异常函数应该指示错误;异常的其他用途可能不会。例如,Mozilla 中的 JavaScript 1.7 有一个名为“生成器”的扩展,它使用异常来指示序列的结束,异常类型为 StopIteration - 没有提及“错误”,这是有道理的。所以可能有一些疯狂的方法......
    • @Josh - 我在上面的回复是对您编辑之前的原始评论,其中您询问为什么内置异常构造函数使用“错误”一词。新的回复是:你在读什么规格?我链接到的版本将异常称为“异常”。它使用术语“错误异常”来专门指代指示错误的异常。这不是所有的例外。
    • @Daniel:对不起。我在阅读所有内容之前发布,这就是我编辑评论的原因。我现在看到规范中定义了ErrorsExceptions Error Exceptions... 导致我认为我应该完全更改我的代码以检测捕获的对象是一个错误或异常...
    • 好的 - 我的意思是,如果您在记录的内容中包含 ex.name,您将能够查看它是否是错误或其他什么,无需以任何其他方式对其进行分类。我还添加了一些关于处理其他问题的想法。
    【解决方案3】:

    异常是您可能期望的,例如在尝试打开文件时可能会遇到“找不到文件异常”。另一方面,错误是您可能看不到的东西,例如堆栈溢出或内存不足。

    异常是不产生逻辑结果的函数的替代逻辑方法。例外还可以更好地解释为什么会以这种方式存在。同样,对于文件打开,文件句柄是一个逻辑结果,如果文件不存在(一个可能的例外)或者它是文件夹而不是文件(另一个可能的例外)。

    【讨论】:

    • +1:这与我对这个主题的想法相似。可能会出现异常,但可能不会出现错误。
    • 所以如果我理解正确,你建议我应该根据实际发生的情况进行登录?也就是说,我确定什么时候是错误,什么时候是异常? IE 如果它是围绕 AJAX 调用的 try/catch 块,则它是一个异常,但是内存不足错误是一个错误?
    • 异常是不产生逻辑结果的函数的替代方法。例外还可以更好地解释为什么会以这种方式存在。同样,对于文件打开,文件句柄是一个逻辑结果,如果文件不存在(一个可能的例外)或者它是文件夹而不是文件(另一个可能的例外)。正是这种情况我会使用异常。所以 AJAX 调用应该抛出异常。 :-D
    【解决方案4】:

    在 JavaScript 中称为错误捕获。所以我建议你使用错误而不是异常。 使用“e”将选项留在中间。就像 Mozilla 的例子一样。 Mozilla Core JavaScript 1.5 Reference

    【讨论】:

    • 啊……但是w3schools.com/js/js_throw.asp 说“throw 语句允许您创建异常。”
    • w3schools 是一套教程,而不是一个权威的参考网站。
    • 可以抛出异常。 catch 语句将该异常作为错误捕获。至少 W3C 是这样描述它的。维基百科和 Mozilla 也是如此。
    【解决方案5】:

    这有点主观,但对我来说,错误是指某人或某事做错、不当或无效的事情。它可能是语法错误、逻辑错误、读取错误、用户错误,甚至是社交错误。这是一个抽象的概念。

    另一方面,异常是在代码中出现特定条件时创建并抛出的对象。它可能对应于概念错误,也可能不对应。所以对我来说,正确的命名是“例外”。

    【讨论】:

    • 我喜欢这个——对我来说很有意义
    • 好的。在与朋友讨论该主题后,我正在认真考虑接受这个答案。这是我的想法。将你所说的与@Pointy 在 cmets 中所说的话相提并论:你可以 throw 任何东西。无论catch 捕获什么都是一个例外。异常可能是错误。因此Exception 是正确的术语。
    • 谢谢。我已经达到了当天的次数限制,所以请随意花点时间。
    • 对你有好处。好吧,我稍后会接受,这将使更多人有机会参与进来。
    • 难道不是Exceptions是意料之中的而是错误的,而Errors是意料之外的吗?
    【解决方案6】:

    你在 Catch 块中得到的是一个异常,所以我将它命名为异常...

    如果这是一个错误 - 我可以在我的代码中处理它并且我通常不希望在 Catch 块中看到它

    HTH。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-16
      • 2022-01-19
      • 1970-01-01
      • 2020-07-11
      • 1970-01-01
      • 2011-04-01
      • 1970-01-01
      相关资源
      最近更新 更多