使用finally语句

时间:2013-08-15 10:49:00

标签: javascript node.js

这是一个非常基本的问题。在Java中,我使用finally语句来关闭资源,因为“这是一个很好的做法”。我在Javascript中开发,然后在几年内在Node.js中开发,我从不使用finally语句。我知道在Node.js中我们所有人都遵循第一个参数错误处理模式。无论如何,以下两个片段也是如此:

try{
    throw 123
}catch (e){

}finally{
    console.log(1)
}

try{
    throw 123
}catch (e){

}

console.log(1)

两者都打印1。

为什么finally是关键字,如果没有真正的好处?清理代码可以放在catch中。

10 个答案:

答案 0 :(得分:12)

  

最终不仅对异常处理有用,它还使程序员避免因返回,继续或中断而意外跳过清理代码。

只是一个简单而直接的示例,显示了差异。有一个return中断了函数的完成,但是在跳过最后一个console.log的同时调用了finally中的console.log

let letsTry = () => {

  try {
    // there is a SyntaxError
    eval('alert("Hello world)');
    
  } catch(error) {
    console.error(error);
	
    // break the function completion
    return;
  } finally {
      console.log('finally')
  }

  console.log('after try cache')
}

letsTry();

答案 1 :(得分:4)

oracle docs为此提供了一个很好的答案。底线:终于被召唤了!即使你只捕获一种异常(不是全局捕获),最后也会被调用(之后如果没有其他捕获,你的应用程序可能会中断)

答案 2 :(得分:4)

但是尝试一下:

try {
    throw "foo"
} catch (e) {
    throw "bar"
} finally {
    console.log("baz")
}

console.log("quux")

如果在catch块内引发了第二个错误,则try...catch块之后的代码将无法运行。
即使finally块中有错误,catch块也将始终运行。

此外,即使finallyreturn语句停止了breaktry块中的代码,catch块也会运行。 return块中的finally语句将覆盖returntry块中的catch语句。

function foo() {
    try {
        return "bar";
    } finally {
        return "baz";
    }
}

foo() // "baz"

答案 3 :(得分:1)

the finally block是出于特殊目的。

  

最终不仅仅用于异常处理 - 它允许程序员避免因返回,继续或中断而意外绕过清理代码。将清理代码放在finally块中总是一种很好的做法,即使没有预期的例外情况也是如此。

因为它不会影响你的业务逻辑,所以它仍然是编译友好的,在内存方面。

答案 4 :(得分:1)

如果try-block提前返回或抛出你不处理的异常怎么办?您仍然希望释放已分配的资源,对吗?


编辑:

问题的答案看起来几乎是哲学的,有一些“猜测”,基本上“我们认为它应该是有用的,因为它存在,所以它应该有用”,“甚至甲骨文也这么说”。或者也许它可以帮助程序员“忘记某些事情”或“意外退出并且没有意识到”。

这几乎是所有正当理由,但也有技术原因。

它有助于在所提到的情况下避免代码重复,其中(a)try块或其中一个catch块返回,或者(b)如果在catch块内抛出第二个异常。

在这些情况下,如果在返回之后和第二次异常之后仍然需要执行某些清理代码或任何其他代码,可以将其放入finally块中,如果要在try和after之后执行它们捕获块。

你可以在没有finally块的情况下完成它,但代码必须重复,finally块允许你避免。这是你真正需要的地方。

因此,如果您确定不会错过(a)或(b)的情况,您仍然可以在try / catch块之后放置'finally'代码并省略finally子句。

但如果情况发生变化怎么办?当您或其他人稍后更改代码时,可能会忘记检查在某些情况下是否现在跳过清理代码。

那么为什么不总是将清理代码放在finally块中呢?这是推荐的以及许多JavaScript程序员所做的事情。

答案 5 :(得分:1)

当你想确保你的代码在最后执行时,即使执行期间有异常,你也可以使用它:

InputStream is = new FileInputStream("C://test.txt");
try {
    //code...
} catch (Exception e) {
    //code...
} finally {
    is.close();
}

答案 6 :(得分:1)

这是一个非常好的问题。

在javascript中几乎没有理由使用finally,但我可以想象它可能具有实际用途的情况。

假设您有一个网页,您可以在某个用户操作后显示某个div,例如点击按钮。
div显示一些日志记录,例如用户请求的操作 操作完成后(错误或无错误),您希望确保再次隐藏div。为此,您可以使用finally子句。

function doSomething() {
    var d = document.getElementById("log");
    show(d);
    try {
        ... execute action ...
    } catch(e) {
        log(e);
    } finally {
        hide(d);
    }
}

通常,正如您所提到的,JavaScript中使用的异常越来越少,以支持错误回调 因此,人们可以问一下,JavaScript中的异常有什么用处。

答案 7 :(得分:0)

在Java中,如果抛出的异常与任何catch-blocks都不匹配,则执行将中断,并且任何打开的资源都将保持打开状态。 即使发生未捕获的异常,也会始终执行finally块。

答案 8 :(得分:0)

问题出在您的示例上。在某些情况下,您不想捕获异常。

try {
    if (Math.random() > 0.5) throw 123
}
finally {
    console.log(1)
}

在这些情况下,如果您不想最终使用该异常,则可以重新抛出异常。

try {
    if (Math.random() > 0.5) throw 123
}
catch (e) {
    console.log(1)
    throw e
}
console.log(1)

或者也许

try {
    if (Math.random() > 0.5) throw 123
    console.log(1)
}
catch (e) {
    console.log(1)
    throw e
}

这两种替代解决方案均会导致代码重复,这就是为什么您需要finally关键字的原因。大多数时间都使用它来释放未使用的资源。忘记它可能导致不必要的锁定或连接或内存泄漏。我猜在某些情况下,即使是智能GC也无法阻止它。

答案 9 :(得分:-2)

也许是这种情况

try{
    throw 123
} finally {
    console.log(1)
}