我想捕获抛出的每个未定义函数错误。JavaScript中是否有全局错误处理工具?用例是从flash中捕获未定义的函数调用。
这对你有帮助吗:
<script type="text/javascript">
window.onerror = function() {
alert("Error caught");
};
xxx();
</script>
我不确定它是如何处理Flash错误的…
更新:它不能在Opera中工作,但我现在正在黑蜻蜓,看看它能得到什么。关于破解蜻蜓的建议来自这个问题:
模拟窗口。onerror在Opera使用javascript
复杂的错误处理
如果你的错误处理非常复杂,因此可能会抛出一个错误本身,添加一个标志来表明你是否已经在“errorHandling-Mode”是很有用的。像这样:
var appIsHandlingError = false;
window.onerror = function() {
if (!appIsHandlingError) {
appIsHandlingError = true;
handleError();
}
};
function handleError() {
// graceful error handling
// if successful: appIsHandlingError = false;
}
否则你会发现自己陷入了一个无限循环。
如何捕捉未处理的Javascript错误
分配窗口。Onerror事件到事件处理程序,如:
<script type="text/javascript">
window.onerror = function(msg, url, line, col, error) {
// Note that col & error are new to the HTML 5 spec and may not be
// supported in every browser. It worked for me in Chrome.
var extra = !col ? '' : '\ncolumn: ' + col;
extra += !error ? '' : '\nerror: ' + error;
// You can view the information in an alert to see things working like this:
alert("Error: " + msg + "\nurl: " + url + "\nline: " + line + extra);
// TODO: Report this error via ajax so you can keep track
// of what pages have JS issues
var suppressErrorAlert = true;
// If you return true, then error alerts (like in older versions of
// Internet Explorer) will be suppressed.
return suppressErrorAlert;
};
</script>
如代码中所示,如果返回window的值。如果Onerror为真,则浏览器应该抑制显示警报对话框。
窗户什么时候开。onerror事件火灾?
简而言之,当1.)存在未捕获的异常或2.)发生编译时错误时引发该事件。
未捕获异常 抛出“一些信息” call_something_undefined (); ,一个安全异常 编译错误 <脚本>{> < /脚本 < >脚本(,)> < /脚本 < >脚本”哦> < /脚本 setTimeout("{", 10);,它将尝试将第一个参数编译为 一个脚本
浏览器支持window.onerror
铬13 + Firefox 6.0 + Internet Explorer 5.5+ Opera 11.60 + Safari 5.1 +
截图:
上面的onerror代码在添加到测试页面后起作用的例子:
<script type="text/javascript">
call_something_undefined();
</script>
AJAX错误报告示例
var error_data = {
url: document.location.href,
};
if(error != null) {
error_data['name'] = error.name; // e.g. ReferenceError
error_data['message'] = error.line;
error_data['stack'] = error.stack;
} else {
error_data['msg'] = msg;
error_data['filename'] = filename;
error_data['line'] = line;
error_data['col'] = col;
}
var xhr = new XMLHttpRequest();
xhr.open('POST', '/ajax/log_javascript_error');
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function() {
if (xhr.status === 200) {
console.log('JS error logged');
} else if (xhr.status !== 200) {
console.error('Failed to log JS error.');
console.error(xhr);
console.error(xhr.status);
console.error(xhr.responseText);
}
};
xhr.send(JSON.stringify(error_data));
JSFiddle:
https://jsfiddle.net/nzfvm44d/
引用:
Mozilla开发者网络::window.onerror 处理和避免网页错误第2部分:运行时错误 返回基础- JavaScript onerror事件 window.onerror可以更好地处理错误 Window onError事件 使用onerror事件来抑制JavaScript错误 SO:: window。在Firefox中未启动onerror
// display error messages for a page, but never more than 3 errors
window.onerror = function(msg, url, line) {
if (onerror.num++ < onerror.max) {
alert("ERROR: " + msg + "\n" + url + ":" + line);
return true;
}
}
onerror.max = 3;
onerror.num = 0;
我建议你试试Trackjs。
它将错误日志记录作为一种服务。
设置起来非常简单。只需要在每页中添加一行<script>就可以了。这也意味着如果你决定不喜欢它,它将非常简单地删除。
还有其他服务,如Sentry(如果你可以托管自己的服务器,它是开源的),但它不能做Trackjs所做的事情。Trackjs记录用户在浏览器和web服务器之间的交互,这样你就可以实际跟踪导致错误的用户步骤,而不仅仅是文件和行号引用(可能还有堆栈跟踪)。
尝试Atatus,它为现代web应用程序提供高级错误跟踪和真实用户监控。
https://www.atatus.com/
让我来解释一下如何获得在所有浏览器中都相当完整的堆栈跟踪。
JavaScript错误处理
现代Chrome和Opera完全支持ErrorEvent和window.onerror的HTML 5草案规范。在这两个浏览器中,你都可以使用window。Onerror,或者正确地绑定到'error'事件:
// Only Chrome & Opera pass the error object.
window.onerror = function (message, file, line, col, error) {
console.log(message, "from", error.stack);
// You can send data to your server
// sendError(data);
};
// Only Chrome & Opera have an error attribute on the event.
window.addEventListener("error", function (e) {
console.log(e.error.message, "from", e.error.stack);
// You can send data to your server
// sendError(data);
})
不幸的是,Firefox、Safari和IE仍然存在,我们也必须支持它们。由于在窗口中无法使用堆栈跟踪。一旦出错,我们就得再做一点工作。
事实证明,要从错误中获得堆栈跟踪,我们唯一能做的就是将所有代码包装在一个try{}catch(e){}块中,然后查看e.stack。我们可以使用一个名为wrap的函数来简化这个过程,该函数接受一个函数并返回一个具有良好错误处理的新函数。
function wrap(func) {
// Ensure we only wrap the function once.
if (!func._wrapped) {
func._wrapped = function () {
try{
func.apply(this, arguments);
} catch(e) {
console.log(e.message, "from", e.stack);
// You can send data to your server
// sendError(data);
throw e;
}
}
}
return func._wrapped;
};
这个作品。任何手动包装的函数都有很好的错误处理,但事实证明,在大多数情况下,我们实际上可以自动为您做这件事。
通过改变addEventListener的全局定义,使它自动包装回调,我们可以在大多数代码中自动插入try{}catch(e){}。这让现有代码继续工作,但增加了高质量的异常跟踪。
var addEventListener = window.EventTarget.prototype.addEventListener;
window.EventTarget.prototype.addEventListener = function (event, callback, bubble) {
addEventListener.call(this, event, wrap(callback), bubble);
}
我们还需要确保removeEventListener继续工作。目前不会,因为addEventListener的参数已经改变。同样,我们只需要在原型对象上修复这个:
var removeEventListener = window.EventTarget.prototype.removeEventListener;
window.EventTarget.prototype.removeEventListener = function (event, callback, bubble) {
removeEventListener.call(this, event, callback._wrapped || callback, bubble);
}
将错误数据传输到后端
您可以使用图像标签发送错误数据,如下所示
function sendError(data) {
var img = newImage(),
src = 'http://yourserver.com/jserror&data=' + encodeURIComponent(JSON.stringify(data));
img.crossOrigin = 'anonymous';
img.onload = function success() {
console.log('success', data);
};
img.onerror = img.onabort = function failure() {
console.error('failure', data);
};
img.src = src;
}
免责声明:我是https://www.atatus.com/的web开发人员。
似乎是那个窗口。Onerror不提供对所有可能错误的访问。具体来说,它忽略了:
<img>加载错误(响应>= 400)。 <脚本>加载错误(响应>= 400)。 如果你的应用程序中有许多其他库也在操纵窗口,则会出现全局错误。以未知的方式出现Onerror (jquery, angular等)。 可能在探索这个之后,我还没有遇到很多情况(iframes,堆栈溢出等)。
下面是一个脚本的开头,它可以捕捉到很多这样的错误,这样你就可以在开发过程中为你的应用程序添加更健壮的调试。
(function(){
/**
* Capture error data for debugging in web console.
*/
var captures = [];
/**
* Wait until `window.onload`, so any external scripts
* you might load have a chance to set their own error handlers,
* which we don't want to override.
*/
window.addEventListener('load', onload);
/**
* Custom global function to standardize
* window.onerror so it works like you'd think.
*
* @see http://www.quirksmode.org/dom/events/error.html
*/
window.onanyerror = window.onanyerror || onanyerrorx;
/**
* Hook up all error handlers after window loads.
*/
function onload() {
handleGlobal();
handleXMLHttp();
handleImage();
handleScript();
handleEvents();
}
/**
* Handle global window events.
*/
function handleGlobal() {
var onerrorx = window.onerror;
window.addEventListener('error', onerror);
function onerror(msg, url, line, col, error) {
window.onanyerror.apply(this, arguments);
if (onerrorx) return onerrorx.apply(null, arguments);
}
}
/**
* Handle ajax request errors.
*/
function handleXMLHttp() {
var sendx = XMLHttpRequest.prototype.send;
window.XMLHttpRequest.prototype.send = function(){
handleAsync(this);
return sendx.apply(this, arguments);
};
}
/**
* Handle image errors.
*/
function handleImage() {
var ImageOriginal = window.Image;
window.Image = ImageOverride;
/**
* New `Image` constructor. Might cause some problems,
* but not sure yet. This is at least a start, and works on chrome.
*/
function ImageOverride() {
var img = new ImageOriginal;
onnext(function(){ handleAsync(img); });
return img;
}
}
/**
* Handle script errors.
*/
function handleScript() {
var HTMLScriptElementOriginal = window.HTMLScriptElement;
window.HTMLScriptElement = HTMLScriptElementOverride;
/**
* New `HTMLScriptElement` constructor.
*
* Allows us to globally override onload.
* Not ideal to override stuff, but it helps with debugging.
*/
function HTMLScriptElementOverride() {
var script = new HTMLScriptElement;
onnext(function(){ handleAsync(script); });
return script;
}
}
/**
* Handle errors in events.
*
* @see http://stackoverflow.com/questions/951791/javascript-global-error-handling/31750604#31750604
*/
function handleEvents() {
var addEventListenerx = window.EventTarget.prototype.addEventListener;
window.EventTarget.prototype.addEventListener = addEventListener;
var removeEventListenerx = window.EventTarget.prototype.removeEventListener;
window.EventTarget.prototype.removeEventListener = removeEventListener;
function addEventListener(event, handler, bubble) {
var handlerx = wrap(handler);
return addEventListenerx.call(this, event, handlerx, bubble);
}
function removeEventListener(event, handler, bubble) {
handler = handler._witherror || handler;
removeEventListenerx.call(this, event, handler, bubble);
}
function wrap(fn) {
fn._witherror = witherror;
function witherror() {
try {
fn.apply(this, arguments);
} catch(e) {
window.onanyerror.apply(this, e);
throw e;
}
}
return fn;
}
}
/**
* Handle image/ajax request errors generically.
*/
function handleAsync(obj) {
var onerrorx = obj.onerror;
obj.onerror = onerror;
var onabortx = obj.onabort;
obj.onabort = onabort;
var onloadx = obj.onload;
obj.onload = onload;
/**
* Handle `onerror`.
*/
function onerror(error) {
window.onanyerror.call(this, error);
if (onerrorx) return onerrorx.apply(this, arguments);
};
/**
* Handle `onabort`.
*/
function onabort(error) {
window.onanyerror.call(this, error);
if (onabortx) return onabortx.apply(this, arguments);
};
/**
* Handle `onload`.
*
* For images, you can get a 403 response error,
* but this isn't triggered as a global on error.
* This sort of standardizes it.
*
* "there is no way to get the HTTP status from a
* request made by an img tag in JavaScript."
* @see http://stackoverflow.com/questions/8108636/how-to-get-http-status-code-of-img-tags/8108646#8108646
*/
function onload(request) {
if (request.status && request.status >= 400) {
window.onanyerror.call(this, request);
}
if (onloadx) return onloadx.apply(this, arguments);
}
}
/**
* Generic error handler.
*
* This shows the basic implementation,
* which you could override in your app.
*/
function onanyerrorx(entity) {
var display = entity;
// ajax request
if (entity instanceof XMLHttpRequest) {
// 400: http://example.com/image.png
display = entity.status + ' ' + entity.responseURL;
} else if (entity instanceof Event) {
// global window events, or image events
var target = entity.currentTarget;
display = target;
} else {
// not sure if there are others
}
capture(entity);
console.log('[onanyerror]', display, entity);
}
/**
* Capture stuff for debugging purposes.
*
* Keep them in memory so you can reference them
* in the chrome debugger as `onanyerror0` up to `onanyerror99`.
*/
function capture(entity) {
captures.push(entity);
if (captures.length > 100) captures.unshift();
// keep the last ones around
var i = captures.length;
while (--i) {
var x = captures[i];
window['onanyerror' + i] = x;
}
}
/**
* Wait til next code execution cycle as fast as possible.
*/
function onnext(fn) {
setTimeout(fn, 0);
}
})();
它可以这样使用:
window.onanyerror = function(entity){
console.log('some error', entity);
};
完整的脚本有一个默认实现,它尝试打印出它接收到的实体/错误的半可读的“显示”版本。可以为特定于应用程序的错误处理程序提供灵感。默认实现还保留了对最后100个错误实体的引用,所以你可以在它们发生后在web控制台中检查它们:
window.onanyerror0
window.onanyerror1
...
window.onanyerror99
注意:这是通过覆盖几个浏览器/本地构造函数上的方法来实现的。这可能会产生意想不到的副作用。然而,在开发过程中使用它,找出错误发生的位置,在开发过程中向NewRelic或Sentry等服务发送日志,这样我们就可以在开发过程中测量错误,在阶段中,我们可以在更深层次上调试正在发生的事情。然后可以在生产环境中关闭它。
希望这能有所帮助。
还应该保留之前关联的onerror回调
<script type="text/javascript">
(function() {
var errorCallback = window.onerror;
window.onerror = function () {
// handle error condition
errorCallback && errorCallback.apply(this, arguments);
};
})();
</script>
你可以通过给window.onerror赋值函数来监听onerror事件:
window.onerror = function (msg, url, lineNo, columnNo, error) {
var string = msg.toLowerCase();
var substring = "script error";
if (string.indexOf(substring) > -1){
alert('Script Error: See Browser Console for Detail');
} else {
alert(msg, url, lineNo, columnNo, error);
}
return false;
};
如果你想用统一的方法来处理未捕获的错误和未处理的承诺拒绝,你可以看看uncaught库。
EDIT
<script type="text/javascript" src=".../uncaught/lib/index.js"></script>
<script type="text/javascript">
uncaught.start();
uncaught.addListener(function (error) {
console.log('Uncaught error or rejection: ', error.message);
});
</script>
它听窗户。除了window.onerror之外,unhandledrejject。
推荐文章
- 如何在Typescript中解析JSON字符串
- Javascript reduce()在对象
- 在angularJS中& vs @和=的区别是什么
- 错误"Uncaught SyntaxError:意外的标记与JSON.parse"
- JavaScript中的querySelector和querySelectorAll vs getElementsByClassName和getElementById
- 给一个数字加上st, nd, rd和th(序数)后缀
- 如何以编程方式触发引导模式?
- setTimeout带引号和不带括号的区别
- 在JS的Chrome CPU配置文件中,'self'和'total'之间的差异
- 用javascript检查输入字符串中是否包含数字
- 如何使用JavaScript分割逗号分隔字符串?
- 在Javascript中~~(“双波浪号”)做什么?
- 谷歌chrome扩展::console.log()从后台页面?
- 未捕获的SyntaxError:
- [].slice的解释。调用javascript?