资讯专栏INFORMATION COLUMN

慎用try catch

lvzishen / 3027人阅读

摘要:捕获不到异步错误尝试对异步方法进行操作只能捕获当次事件循环内的异常,对执行时抛出的异常将无能为力。这里并不能捕获回调里面抛出的异常异步情况想捕获异常,建议在异步函数里包一层。前端可以用在上传图片使用别人的库报错同步调接口等地方适用。

前言

自从ECMA-262第3版引入了try catch语句,作为JavaScript中处理异常的一种标准方式。基本的语法如下所示。

一、try catch基本语法
try {
    //可能会导致错误的代码
} catch (error) {
    //在错误发生时怎么处理
}finally {
     //即使报错始终执行
 }
二、try catch特点
1.try catch耗性能
1.1 try catch耗性能原理

ECMAScript 2015 -The try Statement

13.15.5 Static Semantics: VarDeclaredNames

TryStatement : try Block Catch Finally

1.Let names be VarDeclaredNames of Block.

2.Append to names the elements of the VarDeclaredNames of Catch.

3.Append to names the elements of the VarDeclaredNames of Finally.

4.Return names.

13.15.6 Static Semantics: VarScopedDeclarations

TryStatement : try Block Catch Finally

1.Let declarations be VarScopedDeclarations of Block.

2.Append to declarations the elements of the VarScopedDeclarations of Catch.

3.Append to declarations the elements of the VarScopedDeclarations of Finally.

4.Return declarations.

根据上面ECMAScript文档的13.15.513.15.6`。

下面仅为本妹子自己的翻译理解,仅供参考

上面大概说运行try catch时,需要将当前的词法环境和作用域全部分别添加到catchFinally所要执行的代码块中。从上可以推断出try catch是消耗性能的。

1.2 try catch耗性能实验

下面我用Chrome62IE9分别添加多个try catch,进行对比实验,虽然,很想抛弃万恶的IE,但是很多国内的产品不答应呀,除非我们去健身房再多练练,打一架,嘿嘿~~
1.2.1 实验数据:

//没有加try catch
(function () {
  var i = 0;
     i++;
}())
//有try catch
(function () {
  var i = 0;
    try {
      i++;
    } catch (ex) {
    } finally {
    }
}())

1.2.2 实验结果:

1.2.3 实验链接:

https://jsperf.com/test-try-catch3

https://jsperf.com/test-try-catch

上面实验数据对比得知,try catch会消耗性能,但是try catchChrome的影响比IE11小很多,据说是V8引擎新的编译器TurboFan 起到的作用,有兴趣的小伙伴们可以看下v8_8h_source的3354行起,但是IE11是slower不少的。这就根据小伙伴们的业务对象了,如果只面向现代浏览器,try catch消耗性能影响会很小;如果需要兼容IE或内嵌在低端的webView时,可适当考虑下try catch消耗性能。

2.try catch捕获不到异步错误

尝试对异步方法进行try catch操作只能捕获当次事件循环内的异常,对callback执行时抛出的异常将无能为力。

try {
    setTimeout(()=>{
        const A = 1
        A = 2
    },0)
} catch (err) {
    // 这里并不能捕获回调里面抛出的异常
    console.log("-----catch error------")
    console.log(err)
}

异步情况想捕获异常,建议在异步函数里包一层try catch

setTimeout(() => {
  try {
    const A = 1
    A = 2
  } catch (err) {
    console.log(err)
  }
}, 0)
3.try catch抛出错误

try-catch 语句相配的还有一个 throw 操作符,随时抛出自定义错误,可以根据不同错误类型,创建自定义错误消息。

throw new Error("Something bad happened.");
throw new SyntaxError("I don’t like your syntax.");
throw new TypeError("What type of variable do you take me for?"); throw new RangeError("Sorry, you just don’t have the range.");
throw new EvalError("That doesn’t evaluate.");
throw new URIError("Uri, is that you?");
throw new ReferenceError("You didn’t cite your references properly.");

如果觉得自定义的报错不合理,想看原生报错,可以使用ChromePause on exceptions功能

三、慎用try catch

try catch最适合处理那些我们无法控制的错误,如I/O操作等,后端nodeJsjava读取I/O操作比较多比如读数据库,所以用try catch比较多。前端可以用在上传图片、使用别人的js库报错、async await同步调接口等地方适用。

async function f() {
  try {
    await Promise.reject("出错了");
  } catch(e) {
  }
  return await Promise.resolve("hello world");
}

但是大部分前端客户端代码处理都不怎么依赖环境也没有I/O操作,都是自己写的代码,在明明白白地知道自己的代码会发生错误时,再使用try catch语句就不太合适了,对应数据类型的错误,建议小伙伴们用解构赋值指定默认值、&&||来规避,所以慎用try catch。

foo = (obj = {}) => {
  let obj1 = result || {};
  if (obj && obj.code) {
    console.log("obj.code",obj.code)
  }
}
参考资料

https://raoenhui.github.io/js/2018/12/16/tryCatch

ECMAScript 2015 -The try Statement

https://developers.google.com/web/updates/2015/05/automatically-pause-on-any-exception

https://v8docs.nodesource.com/node-0.8/d4/da0/v8_8h_source.html

Happy coding .. :)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/100675.html

相关文章

  • 慎用ThreadLocal

    摘要:另载于是个很爽的东西,线程安全,能当全局变量来用别。第一家公司,使用框架老技术,现代人可以理解为类似,对每个请求都套上,进入时把写入,返回或抛注意时清理。第二家公司,某次引入一个设计,也用了来传递上下文信息,有的地方没能清掉。 另载于 http://www.qingjingjie.com/blogs/12 ThreadLocal是个很爽的东西,线程安全,能当全局变量来用(别!)。 上一...

    harriszh 评论0 收藏0
  • Java性能优化-慎用异常

    摘要:当创建一个异常时,需要收集一个栈跟踪,这个栈跟踪用于描述异常是在何处创建的。招致性能损失的并不是操作尽管在没有预先创建异常的情况下就抛出异常是有点不寻常。异常是为异常的情况而设计的,使用时也应该牢记这一原则。 当创建一个异常时,需要收集一个栈跟踪(stack track),这个栈跟踪用于描述异常是在何处创建的。构建这些栈跟踪时需要为运行时栈做一份快照,正是这一部分开销很大。 当需要创建...

    hufeng 评论0 收藏0
  • 高性能JavaScript阅读简记(一)

    摘要:对于直接量和局部变量的访问性能差异微不足道,性能消耗代价高一些的是全局变量数组项对象成员。当一个函数被创建后,作用域链中被放入可访问的对象。同样会改变作用域链,带来性能问题。 早前阅读高性能JavaScript一书所做笔记。 一、Loading and Execution 加载和运行 从加载和运行角度优化,源于JavaScript运行会阻塞UI更新,JavaScript脚本的下载、解析...

    sorra 评论0 收藏0
  • 高性能JavaScript阅读简记(一)

    摘要:对于直接量和局部变量的访问性能差异微不足道,性能消耗代价高一些的是全局变量数组项对象成员。当一个函数被创建后,作用域链中被放入可访问的对象。同样会改变作用域链,带来性能问题。 早前阅读高性能JavaScript一书所做笔记。 一、Loading and Execution 加载和运行 从加载和运行角度优化,源于JavaScript运行会阻塞UI更新,JavaScript脚本的下载、解析...

    zhangrxiang 评论0 收藏0
  • Java反射的封装

    摘要:每次看到很多人使用原生的反射接口,我心里都在想,愚蠢的人类啊,为什么不封装一下再用。幸运的是类的封装已经帮你实现了。 Java这种以啰嗦著称的编程语言,反射代码也很啰嗦。每次看到很多人使用原生的反射接口,我心里都在想,愚蠢的人类啊,为什么不封装一下再用。 能用到反射的场景 不能静态决定,比如根据URL参数的字符串调用相应方法的时候。 避免样板代码的时候,例如可以用反射代替,繁琐的JS...

    raledong 评论0 收藏0

发表评论

0条评论

lvzishen

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<