【问题标题】:Javascript try...catch...else...finally like Python, Java, Ruby, etcJavascript try...catch...else...finally like Python, Java, Ruby, etc
【发布时间】:2011-06-19 19:41:15
【问题描述】:

Javascript如何复制其他语言支持的四部分try-catch-else-finally执行模型?

Python 2.5 what's new 提供了清晰、简短的摘要。在 Javascript 术语中:

// XXX THIS EXAMPLE IS A SYNTAX ERROR
try {
  // Protected-block
} catch(e) {
  // Handler-block
} else {
  // Else-block
} finally {
  // Final-block
}

Protected-block中的代码被执行。如果代码抛出异常,则执行Handler-block;如果没有抛出异常,则执行 Else-block

无论之前发生了什么,Final-block 都会在代码块完成并处理任何抛出的异常后执行。即使 Handler-blockElse-block 出现错误并引发新的异常,Final-block 中的代码仍会运行.

请注意,将 Else-block 剪切并粘贴到 Protected-block 的末尾是错误的。如果 Else-block 发生错误,不得Handler-block 处理。

【问题讨论】:

    标签: javascript try-catch


    【解决方案1】:

    如果问题是常见的问题,如果第一个回调抛出未捕获的错误,则不希望调用错误回调,这是另一种解决方案。 ...即在概念上你想要...

    try { 
        //do block 
        cb(null, result);
    } catch(err) {
        // err report
        cb(err)
    }
    

    但是success cb中的一个错误导致cb被第二次调用的问题。所以我开始使用

    try { 
        //do block 
        try { 
            cb(null, result); 
        } catch(err) { 
            // report uncaught error 
        }
    } catch(err) {
        // err report
        cb(err)
    }
    

    这是@cbarrick 解决方案的一个变体。

    【讨论】:

      【解决方案2】:

      我知道这是旧的,但这是一个纯语法解决方案,我认为这是正确的方法:

      try {
          // Protected-block
          try {
              // Else-block
          } catch (e) {
              // Else-handler-block
          }
      } catch(e) {
          // Handler-block
      } finally {
          // Final-block
      }
      

      Protected-block中的代码被执行。如果代码抛出错误,则执行Handler-block;如果没有抛出错误,则执行 Else-block

      无论之前发生了什么,Final-block 都会在代码块完成并处理任何抛出的错误后执行。即使 Handler-blockElse-block 出现错误,Final-block 中的代码仍会运行。

      如果在 Else-block 中抛出错误,它Handler-block 处理,而是由 其他处理程序块

      如果你知道 Else-block 不会抛出:

      try {
          // Protected-block
          // Else-block
      } catch(e) {
          // Handler-block
      } finally {
          // Final-block
      }
      

      故事的寓意,不要害怕缩进;)

      注意:这仅在 Else-handler-block 永不抛出时才有效。

      【讨论】:

      • 干净整洁,不会产生额外的复杂性或依赖性。我喜欢这个解决方案。
      • 比添加success 变量要好得多...除非您希望else 块中引发的任何错误冒泡并且 被主处理程序块捕获,这是 Python 语法所允许的。如果这就是您所需要的,那么如果没有某种 success 变量,我看不到任何方法。
      • 派对迟到了,但这不适用于测试。
      【解决方案3】:

      我知道这个问题已经过时并且已经给出了答案,但我认为我的答案是在 javascripts try-catch-block 中获得“else”的最简单的方法。

      var error = null;
      try {
          /*Protected-block*/
      } catch ( catchedError ) {
          error = catchedError; //necessary to make it available in finally-block
      } finally {
          if ( error ) {
              /*Handler-block*/
              /*e.g. console.log( 'error: ' + error.message );*/
          } else {
              /*Else-block*/
          }
          /*Final-block*/
      }
      

      【讨论】:

        【解决方案4】:

        稍微扩展 jhs 的概念,整个概念可以放在一个函数中,以提供更多的可读性:

        var try_catch_else_finally = function(protected_code, handler_code, else_code, finally_code) {
          try {
            var success = true;
            try {
              protected_code();
            } catch(e) {
              success = false;
              handler_code({"exception_was": e});
            }
            if(success) {
              else_code();
            }
          } finally {
            finally_code();
          }
        };
        

        那我们就可以这样使用了(很像python的方式):

        try_catch_else_finally(function() {
          // protected block
        }, function() {
          // handler block
        }, function() {
          // else block
        }, function() {
          // final-block
        });
        

        【讨论】:

        • 完全。我正在考虑做一个快速的 NPM 模块来做到这一点。我将其排除在我的答案之外,因为您要小心,因为 this 的值将与简单的嵌套 try 相比发生变化。然而我的第二个例子也有这个错误。
        • 对。我们可能希望将调用者的this 绑定到四个回调。让我们称之为读者练习;)
        • 刚刚发生在这件事上。请注意,在较新版本的 JavaScript 中,“胖箭头”表示法使语法更具可读性。
        • 这行得通,但你失去了控制流。你不能 return 来自 try、continue 循环等。
        【解决方案5】:

        Javascript 没有支持无异常情况的语法。最好的解决方法是嵌套try 语句,类似于PEP 341 中的“遗留”技术

        // A pretty-good try/catch/else/finally implementation.
        try {
          var success = true;
          try {
            protected_code();
          } catch(e) {
            success = false;
            handler_code({"exception_was": e});
          }
          if(success) {
            else_code();
          }
        } finally {
          this_always_runs();
        }
        

        除了可读性之外,唯一的问题是success 变量。如果protected_code 设置window.success = false,这将不起作用。一种可读性较差但更安全的方法是使用函数命名空间:

        // A try/catch/else/finally implementation without changing variable bindings.
        try {
          (function() {
            var success = true;
            try {
              protected_code();
            } catch(e) {
              success = false;
              handler_code({"exception_was": e});
            }
            if(success) {
              else_code();
            }
          })();
        } finally {
          this_always_runs();
        }
        

        【讨论】:

        • 对于第一个例子 - 你总是可以使用 new Boolean() true/false 而不是 success = false|true - new Boolean() 创建布尔对象,当与存在比较时返回 true 与文字相矛盾false 当检查存在时将返回 false
        猜你喜欢
        • 2011-10-31
        • 2011-11-17
        • 2011-06-01
        • 2015-09-05
        • 1970-01-01
        • 2014-11-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多