为啥 try..catch..finally 块的 finally 节在 catch 之前运行?

Posted

技术标签:

【中文标题】为啥 try..catch..finally 块的 finally 节在 catch 之前运行?【英文标题】:Why does the finally stanza of a try..catch..finally block get run before catch?为什么 try..catch..finally 块的 finally 节在 catch 之前运行? 【发布时间】:2020-01-16 21:46:41 【问题描述】:
try 
  throw new Error('yikes!');
 catch (e) 
  throw e;
 finally 
  console.log('caught error!')

打印出来:

caught error!
Error: yikes!

那么finally 块是否在 throw 语句之前运行?

它只是看起来像 finally 块首先运行,但我们可以看到实际情况并非如此:

let failed;

try 
  throw new Error('yikes!');
  failed = false;
 catch (e) 
  failed = true;
  throw e;
 finally 
  console.log(`caught error! failed: $failed`)

打印

caught error! failed: true
Error: yikes!

那么为什么错误的打印是带外的呢?这里有一些我没有看到的异步行为吗?

【问题讨论】:

没有catch之前运行,因此failedtrue编辑后:因此foo被记录第一的)。你似乎已经用那个实验回答了你自己的问题;这种行为的哪一部分仍不清楚? 您真的应该运行try throw; catch(e) console.log("caught"); finally console.log("final"); 以查看块的运行顺序。 (如果你不重新抛出异常,它最终不会被打印出来) 【参考方案1】:

    尝试运行 - 您的尝试运行并引发错误

    Catch 运行 - 您的 catch 捕获错误并简单地重新抛出它。

    终于运行了 - 你打印出你的字符串

    重新抛出的错误现在未被捕获 - 您的浏览器会记录有关该错误的详细信息

【讨论】:

【参考方案2】:

finally 子句在整个 try 块完成之前运行。记录的错误发生在运行时截获异常时,即try 块完成之后。 (请注意,您的 catch 代码没有 console.log() 任何内容。它会引发一个新异常,但 finally 子句仍将在世界其他地方看到之前运行。)

我所知道的带有try catch finally 的所有语言的行为方式完全相同。 finally 块的意义在于提供一个放置代码的地方,保证无论try 成功还是失败都可以运行。

【讨论】:

【参考方案3】:

throw 语句不打印任何内容。当浏览器捕获抛出的错误时,稍后会打印该错误。

【讨论】:

以上是关于为啥 try..catch..finally 块的 finally 节在 catch 之前运行?的主要内容,如果未能解决你的问题,请参考以下文章

java try catch finally return执行顺序

为啥使用 NSError 间接参数而不是 @try/@catch/@finally

当它应该表现得像 try/catch/finally 时,为啥使用会抛出异常?

java中的“try - catch -finally”结构中的“finally”都有哪些用途

C# try catch finally 里面写Exception e是为啥?这个e有啥用?Exception e能改成别的吗?

2020.7.24第十九天