ReferenceError
对象是
引用一个不存在的变量
时发生的错误
RangeError
对象是一个
值超出有效范围
时发生的错误(一是
数组长度为负数
,二是
Number
对象的方法参数超出范围,以及函数堆栈超过最大值)
TypeError
对象是变量或参数不是预期类型时发生的错误:对字符串、布尔值、数值等原始类型的值使用
new
命令
URIError
对象是 URI 相关函数的参数不正确时抛出的错误:使用函数不当
eval
函数没有被正确执行时,会抛出
EvalError
错误 - 不再使用,为了代码兼容
自定义错误
function UserError(message) {
this.message = message || "默认信息";
this.name = "UserError";
UserError.prototype = new Error();
UserError.prototype.constructor = UserError;
new UserError("这是自定义的错误!");
Js运行时错误处理机制
try..catch…finally
范围:用来捕获任何类型的
同步错误
,可以捕获
async / await的代码
,但
无法捕获promise、setTimeout、dom回调(
eg:onclick点击回调)的代码,在回调函数里面写try…catch可以捕获,但包在外面不会捕获,
无法捕获语法错误
异步不捕获原因:
async/await捕获原因:
window.onerror
范围:同步错误和异步错误都可以捕获,但
无法捕获到静态资源异常,或者接口异常
(网络请求异常不会事件冒泡,因此必须在捕获阶段将其捕捉到才行),
无法捕获语法错误
原理:当
JS
运行时错误发生时,
window
会触发一个
ErrorEvent
接口的
error
事件
* @param {String} message 错误信息
* @param {String} source 出错文件
* @param {Number} lineno 行号
* @param {Number} colno 列号
window.onerror = function(message, source, lineno, colno, error) {
console.log("捕获到异常:",{message, source, lineno, colno, error});
补充:window.onerror
函数只有在返回
true
的时候,异常才不会向上抛出,否则即使是知道异常的发生控制台还是会显示
Uncaught Error: xxxxx
onerror
最好写在所有
JS
脚本的前面,否则有可能捕获不到错误;(捕获的是全局错误)
资源加载错误
window.addEventListener(一项资源(如图片或脚本)加载失败,加载资源的元素会触发一个
Event
接口的
error
事件,并执行该元素上的
onerror()
处理函数,有浏览器兼容问题)
注意:只能捕获无法冒泡
window.addEventListener("error", (error) => {
console.log("捕获到异常:", error);
}, true) // 一定要加true,捕获但不冒泡
Script error
跨域的静态资源加载异常捕获(cdn文件等)
跨域文件只会报Script error,没有详细信息,怎么解决:
客户端:script标签添加crossOrigin
服务端:设置:Access-Control-Allow-Origin
没有写
catch
的
Promise
中抛出的错误无法被
onerror
或
try-catch
捕获到
为了防止有漏掉的
Promise
异常,建议在全局增加一个对
unhandledrejection
的监听,用来全局监听
Uncaught Promise Error
window.addEventListener("unhandledrejection", function(e){
console.log(e);
补充:如果去掉控制台的异常显示,需要加上:event.preventDefault();
vue异常捕获
VUE errorHandler
Vue.config.errorHandler = (err, vm, info) => {
console.error("通过vue errorHandler捕获的错误");
console.error(err);
console.error(vm);
console.error(info);
React异常捕获
componentDidCatch(React16)
新概念Error boundary(React16):UI的某部分引起的 JS 错误不会破坏整个程序(只有 class component可以成为一个 error boundaries)
不会捕获以下错误
1.事件处理器
2.异步代码
3.服务端的渲染代码
4.在 error boundaries 区域内的错误
Eg: 全局一个error boundary 组件就够用啦
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
componentDidCatch(error, info) {
// Display fallback UI
this.setState({ hasError: true });
// You can also log the error to an error reporting service
logErrorToMyService(error, info);
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return Something went wrong.
;
return this.props.children;
解决:window 对象的 load 和 beforeunload 事件实现了网页崩溃的监控
window.addEventListener("load", function () {
sessionStorage.setItem("good_exit", "pending");
setInterval(function () {
sessionStorage.setItem("time_before_crash", new Date().toString());
}, 1000);
window.addEventListener("beforeunload", function () {
sessionStorage.setItem("good_exit", "true");
if(sessionStorage.getItem("good_exit") &&
sessionStorage.getItem("good_exit") !== "true") {
insert crash logging code here
alert("Hey, welcome back from your crash, looks like you crashed on: " + sessionStorage.getItem("time_before_crash"));
Service Worker 有自己独立的工作线程,与网页区分开,网页崩溃了,Service Worker一般情况下不会崩溃;
Service Worker 生命周期一般要比网页还要长,可以用来监控网页的状态;
网页可以通过 navigator.serviceWorker.controller.postMessage API 向掌管自己的 SW发送消息。
Ajax 发送数据
因为 Ajax 请求本身也有可能会发生异常,而且有可能会引发跨域问题,一般情况下更推荐使用动态创建 img 标签的形式进行上报。
动态创建 img 标签的形式 更常用,简单,无跨越问题
function report(error) {
let reportUrl = "http://jartto.wang/report";
new Image().src = `${reportUrl}?logs=${error}`;
如果你的网站访问量很大,那么一个必然的错误发送的信息就有很多条,这时候,我们需要设置采集率,从而减缓服务器的压力:
Reporter.send = function(data) {
// 只采集 30%
if(Math.random() < 0.3) {
send(data) // 上报错误信息
js源代码压缩如何定位:成熟方案提供sentry
sentry 是一个实时的错误日志追踪和聚合平台,包含了上面 sourcemap 方案,并支持更多功能,如:错误调用栈,log 信息,issue管理,多项目,多用户,提供多种语言客户端等,
这里不过多叙述,之后在搭建sentry服务时,会再补篇博文
补充:node服务端错误处理机制
全栈开发,后端采用express库,在这里补充一下,node服务的错误处理方案
一般错误处理:如某种回退,基本上只是说:“有错误,请再试一次或联系我们”。这并不是特别聪明,但至少通知用户,有地方错了——而不是无限加载或进行类似地处理
特殊错误处理为用户提供详细信息,让用户了解有什么问题以及如何解决它,例如,有信息丢失,数据库中的条目已经存在等等
1. 构建一个自定义 Error 构造函数:让我们方便地获得堆栈跟踪
class CustomError extends Error {
constructor(code = "GENERIC", status = 500, ...params) {
super(...params)
if (Error.captureStackTrace) {
Error.captureStackTrace(this, CustomError)
this.code = code
this.status = status
module.exports = CustomError
2.处理路由:对于每一个路由,我们要有相同的错误处理行为
wT:在默认情况下,由于路由都是封装的,所以 Express 并不真正支持那种方式
解决:实现一个路由处理程序,并把实际的路由逻辑定义为普通的函数。这样,如果路由功能(或任何内部函数)抛出一个错误,它将返回到路由处理程序,然后可以传给前端
const express = require("express")
const router = express.Router()
const CustomError = require("../CustomError")
router.use(async (req, res) => {
try {
const route = require(`.${req.path}`)[req.method]
try {
const result = route(req) // We pass the request to the route function
res.send(result) // We just send to the client what we get returned from the route function
} catch (err) {
This will be entered, if an error occurs inside the route function.
if (err instanceof CustomError) {
In case the error has already been handled, we just transform the error
to our return object.
return res.status(err.status).send({
error: err.code,
description: err.message,
} else {
console.error(err) // For debugging reasons
// It would be an unhandled error, here we can just return our generic error object.
return res.status(500).send({
error: "GENERIC",
description: "Something went wrong. Please try again or contact support.",
} catch (err) {
This will be entered, if the require fails, meaning there is either
no file with the name of the request path or no exported function
with the given request method.
res.status(404).send({
error: "NOT_FOUND",
description: "The resource you tried to access does not exist.",
module.exports = router
// 实际路由文件
const CustomError = require("../CustomError")
const GET = req => {
// example for success
return { name: "Rio de Janeiro" }
const POST = req => {
// example for unhandled error
throw new Error("Some unexpected error, may also be thrown by a library or the runtime.")
const DELETE = req => {
// example for handled error
throw new CustomError("CITY_NOT_FOUND", 404, "The city you are trying to delete could not be found.")
const PATCH = req => {
// example for catching errors and using a CustomError
try {
// something bad happens here
throw new Error("Some internal error")
} catch (err) {
console.error(err) // decide what you want to do here
throw new CustomError(
"CITY_NOT_EDITABLE",
"The city you are trying to edit is not editable."
module.exports = {
POST,
DELETE,
PATCH,
3.构建全局错误处理机制
process.on("uncaughtException", (error: any) => {
logger.error("uncaughtException", error)
process.on("unhandledRejection", (error: any) => {
logger.error("unhandledRejection", error)
1.可疑区域增加 Try-Catch
2.全局监控 JS 异常 window.onerror
3.全局监控静态资源异常 window.addEventListener
4.捕获没有 Catch 的 Promise 异常:unhandledrejection
5.VUE errorHandler 和 React componentDidCatch
6.监控网页崩溃:window 对象的 load 和 beforeunload
7.跨域 crossOrigin 解决
http://jartto.wang/2018/11/20...
https://levelup.gitconnected....
https://zhuanlan.zhihu.com/p/... 更详细 待补充
阅读 5108·2021-09-22 15:36
阅读 4421·2021-09-02 10:20
阅读 1665·2019-08-30 15:44
阅读 2441·2019-08-29 14:06
阅读 890·2019-08-29 11:17
阅读 1324·2019-08-26 14:05
阅读 2692·2019-08-26 13:50
阅读 1290·2019-08-26 10:26