常见错误处理

  1. RangeError:范围错误,代码中使用了超出范围的数值

  2. ReferenceError:引用错误,引用的变量/函数不存在

  3. SyntaxError:语法解析错误

  4. TypeError:类型错误,例如对非对象类型使用对象方法、对非函数类型使用函数调用操作符等

  5. URIError:URI 错误,decodeURI('%')代码中使用了不合法的 URI

  6. EvalError:eval()

  7. InternalError:调用栈溢出

异步错误和 try/catch

Error 对象只有在被抛出时才会成为异常。

try/catch 可以捕获同步函数中的错误。

try catch 无法捕获异步函数中的错误

实例代码:

// 异步任务
const task = () => {
  setTimeout(() => {
    throw new Error('async error');
  }, 1000);
};
// 主任务
function main() {
  try {
    task();
  } catch (e) {
    console.log(e, 'err');
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

这种情况下 main 是无法 catch error,原因是异步代码并不在 try catch 上下文中执行。异步任务由 eventloop 加入任务队列,并取出入栈(js 主进程)执行,而当 task 取出执行的时候, main 的栈已经退出了,也就是上下文环境已经改变,所以 main 无法捕获 task 的错误。

用 Promise 捕获异步错误

function task() {
  new Promise((reslove, reject) => {
    setTimeout(() => {
      reject('async error');
    });
  });
}

task().catch((e) => console.log(e));
1
2
3
4
5
6
7
8
9

注意 promise 内部的错误不会冒泡出来,需要通过 promise.catch 才可以捕获,或者使用

async/await

将异步函数变成同步函数执行,那就可以使用 try/catch 捕获

throw Error

try {
  throw new Error('Whoops!');
} catch (e) {
  console.error(e.name + ': ' + e.message);
}
1
2
3
4
5

堆栈跟踪

  1. using try and catch

  2. using stack

console.log(new Error('custom error').stack);
1
  1. using console.trace
console.trace(new Error('My Error'));
1

自定义错误类

class ValidationError extends Error {
  constructor(message) {
    super(message);
    // this.name = 'ValidationError'; // 等同于 get name
  }
  get name() {
    return 'ValidationError';
  }
}
throw ValidationError('未找到该属性: name');
1
2
3
4
5
6
7
8
9
10

可以使用 instanceof 关键字识别它:

try {
  throw ValidationError('未找到该属性: name'); // 抛出 ValidationError 的代码
} catch (e) {
  if (e instanceof ValidationError) {
    //
  }
}
1
2
3
4
5
6
7

使用工具来监控并上报错误

  1. Sentry(https://sentry.io/): 专注于异常(应用崩溃)而不是信息错误。它提供了应用中错误的完整概述,包括受影响的用户数量、调用堆栈、受影响的浏览器以及导致错误的提交等详细信息。

  2. Rollbar(https://rollbar.com/):用于前端、后端和移动应用的无代理错误监控工具。

参考阅读

Last Updated: 2023/2/22 15:29:23
Contributors: licong96