广告位联系
返回顶部
分享到

JavaScript代码不能被阻断的稳定性建设

JavaScript 来源:互联网 作者:佚名 发布时间:2022-10-12 08:23:50 人浏览
摘要

背景 稳定性建设之JavaScript代码不能被阻断 js代码可能会因为某些原因,导致出错,进而整个后续代码有可能都被阻断。直接影响线上的稳定性 最常见的js被阻断的情况 1 2 3 4 5 6 consol

背景

稳定性建设之JavaScript代码不能被阻断

js代码可能会因为某些原因,导致出错,进而整个后续代码有可能都被阻断。直接影响线上的稳定性

最常见的js被阻断的情况

1

2

3

4

5

6

console.log(111)

// 预期 a = {}

// 结果

a = undefined

a.a = 1

console.log(222) // js代码不能执行到这一行

这个代码很明显会报错,在a.a = 1这一行开始报错,后续的js代码被阻断了,console.log(222)打印不出来

解决办法

  • 解决办法也很简单,用 try...catch... 捕获住错误就好了

1

2

3

4

5

6

7

8

9

10

console.log(111)

try {

  // 预期 a = {}

  // 结果

  a = undefined

  a.a = 1

} catch (e) {

  console.error(e)

}

console.log(222) // js代码可以执行到这一行

容易被我们忽视的点

1. 没考虑到错误上报

  • 上面的demo没有考虑错误上报,发生错误时,外部根本捕获不到(即使你接入了sentry类的产品),因为error被try catch给吃掉了

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

try {

  // 预期 a = {}

  // 结果

  a = undefined

  a.a = 1

} catch (e) {

  console.error(e)

  // 公司内部的上报函数

  someReportFunction('sendEvent', {

    name: 'try_catch_error',

    params: {

      errorMsg: e.message,

      errorStack: e.stack

    },

  });

}

2. 错用throw

随便点开一篇文章,就有人在误人子弟,教别人用 throw, throw这个东西是不能乱用的,因为他会阻断代码,重要的事情说三遍,throw会阻断代码,throw会阻断代码,throw会阻断代码

例如:

1

2

3

4

5

6

7

8

9

10

11

console.log(111)

try {

  // 预期 a = {}

  // 结果

  a = undefined

  a.a = 1

} catch (e) {

  console.error(e)

  throw e // throw会阻断代码,导致下面不执行

}

console.log(222) // 不能执行到这一行

当然throw也不是一无是处,但是,他只能在try{ 里面使用 },不能在try之外的地方使用throw,包括catch

1

2

3

4

5

6

7

console.log(111)

try {

  throw new Error(111)

} catch (e) {

  console.error(e)

}

console.log(222)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

function getData () {

    if (...) {

        ...

    } else {

        throw new Error(111)

    }

}

console.log(111)

try {

  getData()

} catch (e) {

  console.error(e)

}

console.log(222)

3. 异步代码catch不到,还是会被阻断

1

2

3

4

5

6

7

8

9

10

11

12

13

14

console.log(111111111)

try {

  setTimeout(() => {

    a = undefined

    a.a = 1 // 代码被阻断于此

    console.log('error') // 不能执行到这一行

  }, 0)

} catch (e) {

  console.error(e) // 异步代码catch不到

}

console.log(222222222)

setTimeout(() => {

  console.log('setTimeout') // 浏览器可以执行到这一行,node的不行(node14和16版本都test了)

}, 2000)

4. import()和require()的错误捕获表现不一致

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

// a.js

console.log(111111111)

try {

  require('./b.js')

} catch (e) {

  console.log('error') // 错误会被正常catch到

  console.error(e)

}

console.log(222222222)

setTimeout(() => {

  console.log('setTimeout')

}, 2000)

// b.js

console.log(1)

a = undefined

a.a = 1

console.log(2)

// 结果打印 (require被正常捕获)

111111111

1

error

TypeError: Cannot set property 'a' of undefined

    ...

    ...

222222222

setTimeout

  • 同样的代码换成,import()

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

// a.js

console.log(111111111)

try {

  import('./b.js')

} catch (e) {

  console.log('error') // 错误没有被catch到

  console.error(e)

}

console.log(222222222)

setTimeout(() => {

  console.log('setTimeout')

}, 2000)

// b.js

console.log(1)

a = undefined

a.a = 1

console.log(2)

// 结果打印 (import的 错误没有被catch到)

111111111

222222222

1

(node:92673) UnhandledPromiseRejectionWarning: TypeError: Cannot set property 'a' of undefined

    ...

setTimeout

正确捕获import()的方式:其实import()是一个promise,用promise的方法去catch就好了

1

2

3

4

5

import('./b.js')

  .catch(e => {

    console.log('error')

    console.error(e)

  })

结论:

  • try catch 不能捕获import()模块的错误,require可以被捕获
  • import() 用promise的方法去catch就好了

背景:

  • require是运行时加载(可以理解为,函数调用)
  • import()是动态import,会延迟加载,是异步任务(微任务),是promise

版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://juejin.cn/post/7152661468235137037
相关文章
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计