Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

错误处理 #23

Open
canvascat opened this issue Jul 15, 2021 · 0 comments
Open

错误处理 #23

canvascat opened this issue Jul 15, 2021 · 0 comments

Comments

@canvascat
Copy link
Owner

常见错误

  1. 脚本错误
    • 语法错误
    • 运行时错误
      • 同步错误
      • 异步错误
      • Promise 错误
  2. 网络错误
    • 资源加载错误
    • 自定义请求错误

语法错误

语法错误无法被try catch 处理,但是一般在开发时就很容易被发现。

同步错误

JS 引擎在执行脚本时,把任务分块压入事件栈,轮询取出执行,每个事件任务都有自己的上下文环境, 在当前上下文环境同步执行的代码发生错误都能被try catch 捕获,保证后续的同步代码被执行。

try {
  // error
} catch (e) {
  console.log(e);
}

异步错误

常见的 setTimeout 等方法会创建新的事件任务插入事件栈中,待后续执行。 所以try catch 无法捕获其他上下文的代码错误。

为了便于分析发生的错误,一般利用 window.onerror 事件来监听错误的发生。 它比try catch的捕获错误信息的能力要强大。

/**
 * @param {Event|string} msg    错误描述
 * @param {?string}      url    报错文件
 * @param {?number}      row    行号
 * @param {?number}      col    列号
 * @param {?Error}       error  错误Error对象
 */
window.onerror = function (msg, url, row, col, error) {
  console.log('window.onerror =>', arguments);
  // return true; // 返回 true 的时候,异常不会向上抛出,控制台不会输出错误
};

image

注意事项

  1. window.onerror 可以捕获常见语法、同步、异步错误等错误;
  2. window.onerror 无法捕获 Promise 错误、网络错误;
  3. window.onerror 应该在所有 JS 脚本之前被执行,以免遗漏;
  4. window.onerror 容易被覆盖,在处理回调时应该考虑,被人也在使用该事件监听。

Promise 错误

如果你在使用 promise 时未 catch 的话,那么 onerror 也无能为力了。

Promise.reject('this is reject');
new Promise((resolve, reject) => {
  reject('promise error');
});
new Promise((resolve) => {
  resolve();
}).then(() => {
  throw 'promise error';
});

同样你可以利用 window.onunhandledrejectionwindow.addEventListener("unhandledrejection")来监控错误。 接收一个PromiseError对象,可以解析错误对象中的 reason 属性,有点类似 stack

window.onunhandledrejection = function () {
  console.log('window.onunhandledrejection => ', arguments);
};

image

具体兼容处理在 TraceKit.js 可以看到。

https://github.com/csnover/TraceKit/blob/8f74ec6bcf7183e979c14e465c7abdd9fe4ce28e/tracekit.js#L280-L288

网络错误

由于网络请求异常不会冒泡,应此需要在事件捕获阶段才能获取到。 我们可以利用 window.addEventListener。比如代码、图片等重要 CDN 资源挂了,能及时获得反馈是极为重要的。

window.addEventListener(
  'error',
  ({ target }) => {
    if (target === window) return; // 避免重复上报
    console.log({
      url: location.href, // 引用资源地址
      src: target.src, // 资源加载出错地址
      tagName: target.tagName,
    });
    // return true; // 中断事件传播
  },
  true
);

image

window.addEventListener 的好处,不怕回调被覆盖,可以监听多个回调函数,但记得销毁避免内存泄漏与错误。

但无法获取 window.onerror 那么丰富的信息。一般只用window.addEventListener 来监控资源加载错误。

上报方式

参考 badjs

https://github.com/BetterJS/badjs-report/blob/a4444c7d790edc1c9b79d79cf46d8719598bd91e/src/bj-report.js#L334-L341

同过将错误信息拼接到 url 中,借助img发起请求上报;或者通过传入处理方法,一般使用ajax

由于 get 请求参数有长度限制,数据太大还是使用post更加稳妥。


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant