基础系列-onerror处理
理论
GlobalEventHandlers.onerror
用于处理 error 事件。
Error
事件的事件处理程序 (en-US),在各种目标对象的不同类型错误被触发:
- 当JavaScript运行时错误(包括语法错误)发生时,
window
会触发一个ErrorEvent
接口的error
事件,并执行window.onerror()
。 - 当一项资源(如
<img>
或<script>
)加载失败,加载资源的元素会触发一个Event
接口的error
事件,并执行该元素上的onerror()
处理函数。这些error事件不会向上冒泡到 window,不过(至少在Firefox中)能被单一的window.addEventListener
(en-US)捕获。可以使用捕获的方式监听到资源加载失败。
加载一个全局的error
事件处理函数可用于自动收集错误报告。
由于历史原因,
window.onerror
和element.onerror
接受不同的参数。
window.onerror
window.onerror = function(message, source, lineno, colno, error) { ... }
函数参数:
message
:错误信息(字符串)。可用于HTMLonerror=""
处理程序中的event
。source
:发生错误的脚本URL(字符串)lineno
:发生错误的行号(数字)colno
:发生错误的列号(数字)error
:Error对象(对象)
若该函数返回true
,则阻止执行默认事件处理函数。
这种方式只能捕获脚本错误问题。
window.addEventListener(‘error’)
window.addEventListener('error', function(event) { ... }) // 冒泡方式只能获取到脚本错误问题
window.addEventListener('error', function(event) { ... }, true) // 捕获方式可以获取到脚本错误和资源加载失败的问题
ErrorEvent
类型的event
包含有关事件和错误的所有信息。
ErrorEvent
事件对象在脚本发生错误时产生,它可以提供发生错误的脚本文件的文件名,以及发生错误时所在的行号等信息。
Event 类型为资源加载失败返回的类型。
Element.onerror
element.onerror = function(event) { ... }
element.addEventListener(‘error’)
可以监听到脚本执行错误或者资源未加载的错误。
html
<div class="controls">
<button id="img-error" type="button">Generate image error</button>
<img class="bad-img" />
</div>
<div class="event-log">
<label>Event log:</label>
<textarea readonly class="event-log-contents" rows="8" cols="30"></textarea>
</div>
js
const log = document.querySelector('.event-log-contents');
const badImg = document.querySelector('.bad-img');
badImg.addEventListener('error', (event) => {
log.textContent = log.textContent + `${event.type}: Loading image\n`;
console.log(event)
});
const imgError = document.querySelector('#img-error');
imgError.addEventListener('click', () => {
badImg.setAttribute('src', 'i-dont-exist');
});
window.addEventListener(‘load’)
当整个页面及所有依赖资源如样式表和图片都已完成加载时,将触发load
事件。
window.addEventListener('load', (event) => {
console.log('page is fully loaded');
});
其他
跨域问题
监听设置的位置问题
实践
公司有做一个白屏检测,检测资源是否未加载。
逻辑为:
先在入口文件中挂载特定的 dom,设置 window.addEventListener(‘load’, callback),监听事件,当首页加载完毕后,响应 load 监听事件判断 dom 是否挂载,如果没有在 dom 树上找到目标元素,则表示发生了白屏事件。
设置 window.addEventListener(‘error’, callback, true) 使用捕获的方式监听到资源加载失败。其中判断 cdn 加载失败,则会重新创建 link 和 script 标签重新加载,如果二次重载的资源错误则表示用户进入了网络链接不稳定的状态。
设置 window.addEventListener(‘load’, callback, false) 监听页面资源加载完成的情况。
手动判断是否资源加载的问题,然后将问题上报到 sentry。
但是不排除代码中出现 undefined 导致的白屏问题,比如说 A 页面跳转到 B 页面需要传参,但是发生了 undefined 的问题,则会直接导致 B 页面白屏。
DEMO
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Error</title>
</head>
<body>
<div>
测试 error
<img src="someimage.png" onerror="handleError(this)" />
error
<div class="controls">
<button id="img-error" type="button">Generate image error</button>
<img class="bad-img" />
</div>
<div class="event-log">
<label>Event log:</label>
<textarea readonly class="event-log-contents" rows="8" cols="30"></textarea>
</div>
<button onclick="makeError()">调用error</button>
</div>
<script>
function handleError(e) {
console.log('handleError: ', e);
}
window.onerror = function(msg, url, line, col, error) {
// 直接将错误打印到控制台
console.log('window.onerror: ', msg, url, line, col, error)
}
window.addEventListener('error', function(event) {
console.log('addEventListener: ', event, event instanceof ErrorEvent);
console.log('addEventListener after: ', event.target.baseURI);
}, true)
window.addEventListener('load', (event) => {
console.log('page is fully loaded');
});
const log = document.querySelector('.event-log-contents');
const badImg = document.querySelector('.bad-img');
badImg.addEventListener('error', (event) => {
log.textContent = log.textContent + `${event.type}: Loading image\n`;
console.log('addEventListener badImg: ', event)
});
const imgError = document.querySelector('#img-error');
imgError.addEventListener('click', () => {
badImg.setAttribute('src', 'i-dont-exist');
});
function makeError () {
var name = "geoff"
var msg = "Hi, " + Name
console.log(msg)
}
</script>
<script src="someimage.js" onerror="handleError(this)"></script>
</body>
</html>
白屏方案
参考链接:https://segmentfault.com/a/1190000040236233
参考链接
GlobalEventHandlers.onerror:https://developer.mozilla.org/zh-CN/docs/Web/API/GlobalEventHandlers/onerror
GlobalEventHandlers:https://developer.mozilla.org/zh-CN/docs/Web/API/GlobalEventHandlers
ErrorEvent:https://developer.mozilla.org/zh-CN/docs/Web/API/ErrorEvent