前端监控sdk开发(三)promise错误捕获

引言

在前端开发中,Promise是一种用于处理异步操作的机制,它可以有效地解决回调地狱的问题。然而,当Promise链中发生错误时,如果没有进行适当的处理,这些错误可能会被忽略或导致应用程序崩溃。为了及时发现和解决这些问题,我们需要在前端监控SDK中实现Promise错误的捕获。

window.addEventListener(‘unhandledrejection’, callback)

unhandledrejection是一个JavaScript中的错误处理机制,用于处理未被捕获的Promise rejection(拒绝)。

当一个Promise被拒绝(rejected)时,如果没有通过catch()或者then()方法的第二个参数来处理这个拒绝,那么就会触发unhandledrejection事件。

unhandledrejection事件是一个全局事件,可以通过window对象的unhandledrejection属性来监听。当这个事件被触发时,可以获取到拒绝的原因(reason)和相关的Promise对象。

通常情况下,我们应该在代码中显式地处理Promise rejection,以避免触发unhandledrejection事件。这可以通过使用catch()方法或者在then()方法中传递第二个参数来实现。这样做可以确保我们能够及时地处理Promise rejection,并避免出现未捕获的错误。

如果没有正确地处理Promise rejection,并且触发了unhandledrejection事件,那么可能会导致应用程序出现未知的错误或者异常行为。因此,在编写JavaScript代码时,我们应该始终注意处理Promise rejection,并确保不会出现未捕获的情况。

window.addEventListener('unhandledrejection', function(event) {
    let lastEvent = getLastEvent()
    let message
    let filename
    let lineno = 0
    let colno = 0
    let stack = ''
    let reason = event.reason
    if (typeof reason === 'string') {
      message = reason
    } else if (typeof reason === 'object') {
      message = reason.message
      if (reason.stack) {
        let matchResult = reason.stack.match(/at\s+(.+):(\d+):(\d+)/)
        filename = matchResult[1]
        lineno = matchResult[2]
        colno = matchResult[3]
      }
      stack = getStackLines(reason.stack)
    }
    tracker.send({
      kind: 'stability', // 稳定性(大类)
      type: 'error', // 小类(js error)
      errorType: 'promiseError', // JS执行错误
      message, // 报错信息
      filename, // 报错文件
      position: `${lineno}:${colno}`, // 报错位置 行:列
      stack,
      selector: lastEvent ? getSelector(lastEvent.path) : '' // 最后一个操作的元素
    })
  }, true)

当发生未处理的 Promise 错误时,浏览器会触发 unhandledrejection 事件,并将错误信息传递给事件处理函数。

在事件处理函数中,首先通过 getLastEvent() 函数获取最后一个用户操作的事件对象。然后定义了一些变量用于存储错误信息,包括 messagefilenamelinenocolnostack

接下来判断错误原因的类型,如果是字符串类型,则将其赋值给 message 变量;如果是对象类型,则将其 message 属性赋值给 message 变量,并且如果存在 stack 属性,则通过正则表达式匹配出文件名、行号和列号,并分别赋值给对应的变量。

最后调用 tracker.send() 方法发送错误信息到远程服务器。其中包括了一些字段,如 kind 表示稳定性大类,这里是 ‘stability’;type 表示错误类型小类,这里是 ‘error’;errorType 表示 JS 执行错误类型,这里是 ‘promiseError’;还有报错信息、报错文件、报错位置、堆栈信息和最后一个操作元素的选择器等。

上述所用到的getLastEventgetStackLinesgetSelector可看前端监控sdk开发(二)js错误捕获

html代码

<div class="container">
  <div class="content">
    <input type="button" value="promiseError" onclick="promiseError()" />
  </div>
</div>

<script>
function promiseError() {
  new Promise(function (resolve, reject) {
    window.someVar.error = 'error'
  }).then(res => {
    console.log(res);
  })
}
</script>

报错event数据截图

前端监控sdk开发(三)promise错误捕获

处理后的数据

{
    "title": "前端监控",
    "url": "http://127.0.0.1:5500/projects/bug-report/packages/sdk/src/index.html",
    "timestamp": 1703151311993,
    "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
    "kind": "stability",
    "type": "error",
    "errorType": "promiseError",
    "message": "Cannot set properties of undefined (setting 'error')",
    "filename": "http://127.0.0.1:5500/projects/bug-report/packages/sdk/src/index.html",
    "position": "52:30",
    "stack": "http://127.0.0.1:5500/projects/bug-report/packages/sdk/src/index.html:52:30^new Promise (<anonymous>)^promiseError (http://127.0.0.1:5500/projects/bug-report/packages/sdk/src/index.html:51:7)^HTMLInputElement.onclick (http://127.0.0.1:5500/projects/bug-report/packages/sdk/src/index.html:20:76)",
    "selector": ""
}

总结

通过监听unhandledrejection事件,我们可以捕获未被.catch()方法处理的Promise错误;在实际开发中,我们可以根据具体需求和场景选择合适的方式来实现Promise错误的捕获,并将捕获到的错误信息发送到监控服务器进行记录和分析,以提高应用程序的稳定性和用户体验。

原文链接:https://juejin.cn/post/7314947185866473523 作者:俊刚

(0)
上一篇 2023年12月22日 上午11:02
下一篇 2023年12月22日 上午11:13

相关推荐

发表回复

登录后才能评论