js错误的实质,也是发出一个事件,处理他
对象属性
message:错误提示信息
name:错误名称(非标准属性)宿主环境赋予
stack:错误的堆栈(非标准属性)宿主环境赋予
对象类型(7种)
SyntaxError对象是解析代码时发生的语法错误
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('这是自定义的错误!');
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
<script src="http://jartto.wang/main.js" crossorigin></script>
使用window.onerror
<iframe src="./iframe.html" frameborder="0"></iframe>
<script>
window.frames[0].onerror = function (message, source, lineno, colno, error) {
console.log('捕获到 iframe 异常:',{message, source, lineno, colno, error});
return true;
};
</script>
没有写 catch 的 Promise 中抛出的错误无法被 onerror 或 try-catch 捕获到
为了防止有漏掉的 Promise 异常,建议在全局增加一个对 unhandledrejection 的监听,用来全局监听Uncaught Promise Error
window.addEventListener("unhandledrejection", function(e){
console.log(e);
});
补充:如果去掉控制台的异常显示,需要加上:event.preventDefault();
VUE errorHandler
Vue.config.errorHandler = (err, vm, info) => {
console.error('通过vue errorHandler捕获的错误');
console.error(err);
console.error(vm);
console.error(info);
}
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 <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
<ErrorBoundary>
<MyWidget />
</ErrorBoundary>
卡顿:网页暂时响应比较慢, JS 可能无法及时执行
解决: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'));
}
崩溃:JS 都不运行了,还有什么办法可以监控网页的崩溃,并将网页崩溃上报呢
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) // 上报错误信息
}
}
sentry 是一个实时的错误日志追踪和聚合平台,包含了上面 sourcemap 方案,并支持更多功能,如:错误调用栈,log 信息,issue管理,多项目,多用户,提供多种语言客户端等,
这里不过多叙述,之后在搭建sentry服务时,会再补篇博文
全栈开发,后端采用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',
400,
'The city you are trying to edit is not editable.'
)
}
}
module.exports = {
GET,
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 解决
原文来自:https://segmentfault.com/a/1190000019226851
vue工程npm run serve/start/dev启动时,node_modules文件报:Cannot read property range of null 错误,该问题是babel-eslint版本更新问题导致的;
在ajax请求后台数据时有时会报 HTTP 400 错误 - 请求无效 (Bad request);出现这个请求无效报错说明请求没有进入到后台服务里;原因:前端提交数据的字段名称或者是字段类型和后台的实体类不一致
我们都知道 try catch 无法捕获 setTimeout 异步任务中的错误,那其中的原因是什么。以及异步代码在 js 中是特别常见的,我们该怎么做才比较?
父页面初始化声明变量a为数组(数组对象是引用类型,赋值传递的是地址),创建iframe子页面后给父页面变量a赋值,赋值后销毁iframe子页面,再次调用变量a的时候就会抛出异常‘SCRIPT5011:不能执行已释放Script的代码’。
文件上传的功能时候,调用fs.renameSync方法错误,这个提示是跨区重命名文件出现的权限问题。先从源文件拷贝到另外分区的目标文件,然后再unlink,就可以了。
如果在JavaScript中使用innerHTML,缺点是:内容随处可见;不能像“追加到innerHTML”一样使用;innerHTML不提供验证,因此我们可能会在文档中插入有效的和破坏性的HTML并将其中断
现在,有越来越多所谓的“教程”来帮助我们提高网站的易用性。我们收集了一些在Web开发中容易出错和被忽略的小问题,并且提供了参考的解决方案,以便于帮助Web开发者更好的完善网站。
为什么要做前端错误监控?1. 为了保证产品的质量2. 有些问题只存在于线上特定的环境3. 后端错误有监控,前端错误没有监控,前端错误分为两类: 即时运行错误和资源加载错误
当我们在进行开发的时候,通常需要属于我们自己的错误类来反映任务中可能出现的特殊情况。对于网络操作错误,我们需要 HttpError,对于数据库操作错误,我们需要 DbError,对于搜索操作错误,我们需要 NotFoundError,等等
最近查看了一些项目后,发现了几个最常见的JavaScript 错误。我们会告诉你什么原因导致了这些错误,以及如何防止这些错误发生。如果你能够避免落入这些 “陷阱”,你将会成为一个更好的开发者。
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!