驳《慎用 try catch》

26,692 阅读3分钟

今天在掘金看到了一篇文章,慎用 try catch,发布者的昵称是“前端妹子”。根据我的经验,这种昵称一般都不是妹子,大概率是营销号(PS:如果能换个美女头像就更走心了)。(这个还真是个妹子,之前言论欠妥,在此先向妹子道歉。)

看完之后我评论道:“很难相信这是 2018 年写的文章”。

一般对于这种孰优孰劣的文章我的态度是直接无视,但是这篇的文章的误导性太大了,有必要反驳一下。

观点一:try catch 耗性能(误)

V8 的 TurboFan 引擎从 2013 年就开始开发,并随 Chrome 59 发布,try/catch 已经可以进行优化了,完全不用再担心性能问题。

观点二:try catch 捕获不到异步错误

第二个是正确的,try/catch 无法捕获异步异常。

但是,不用 try/catch 一样捕获不到。js 对于这种情况确实无能为力。考虑如下代码

setTimeout(()=> {
  throw new Error('can you catch me!!!');
})

无论使用什么方式,都无法捕获异常。归根结底这是代码编写的问题,而非 try/catch 的问题。

观点三:try catch可能会导致报错点更模糊(误)

try/catch 并不会让报错信息变模糊。

try catch 语句中报错直接到 catch 中处理,而浏览器控制台看不到报错信息。

这个锅 try/catch 可不背,这是开发者的锅。

如果有了 --async-stack-traces 参数,异步错误也变得更加清晰。

而另一个观点则暴露了作者的无知:

很多人并没有在catch中抛出报错信息,或改写成自己随意写的报错文言,其实不如直接看浏览器原生的报错修改 bug 更方便

这句话完全错误,不要误导读者了。

首先,js 是单线程,当脚本抛出了未捕获的异常会使得这个脚本挂起,后面的代码无法执行。

再者,即使我们使用了 try/catch,依然可以在浏览器中看到完整的报错栈信息。

如果作者不会使用 Chrome Devtools,我写一个简短的教程。

在我标注了 ① 的地方,这个功能是“Pause on exceptions”,当抛出未捕获的异常时,调试器会在此中断。如果不选中,则只会在控制台输出报错信息,而不会开启调试器并暂停到抛出异常的位置。

在图 ② 的地方,如果选中了,即使我们使用 try/catch 捕获了这个异常,调试器依然会中断在异常的位置。所以放心的使用 try/catch 吧,你的异常信息不会丢失的,不用担心“浏览器控制台看不到报错信息”。

在图 ③ 的地方,就是前面提到的 V8 的 --async-stack-traces 特性,这个在 Chrome 中是默认开启的。我们可以看到异步的堆栈信息,更加方便的调试程序。

对于某些喜欢依赖 console.log 进行调试的开发者们,Chrome Devtools 也很贴心的开发了 logpoints 功能:

对于找不到这个功能的,首先确认浏览器版本是 73。目前稳定版是 71,可以下载 Chrome Canary

地址栏输入:chrome://flags/#enable-devtools-experiments 开启试验功能。然后安装上面的动图设置。

思考

这篇文章带给我们的思考。

  1. 对于读者:不要妄图通过二手资料来学习,对于某个有争议的观点,我们应该去寻找最初的参考来源。
  2. 对于社区:掘金是否应该增加举报或者某些机制,来限制这种“只有流量”,但是“毫无营养”的文章出现在首页。
  3. 对于作者:一般读者期望的文章是“解决方案”,而不是“问题”:我们不希望看到“XXX不好”、“XXX有问题”,我们更欢迎“XXX不好,我们应该YYY”,“XXX有问题,我们应该YYY解决”。