我想捕获每个未定义的函数错误抛出.JavaScript中是否存在全局错误处理工具?用例是捕获未定义的闪存函数调用.
将window.onerror
事件分配给事件处理程序,如:
如上代码注释,如果返回值window.onerror
是true
那么浏览器应该抑制显示一个警告对话框.
简而言之,当1.)存在未捕获的异常或2.)发生编译时错误时引发该事件.
没有被捕的例外
抛出"一些消息"
call_something_undefined();
cross_origin_iframe.contentWindow.document ;,一个安全例外
编译错误
setTimeout("{", 10);
,它将尝试将第一个参数编译为脚本
Chrome 13+
Firefox 6.0+
Internet Explorer 5.5+
Opera 11.60+
Safari 5.1+
将此添加到测试页面后,上面的onerror代码示例:
https://jsfiddle.net/nzfvm44d/
Mozilla Developer Network :: window.onerror
MSDN ::处理和避免网页错误第2部分:运行时错误
返回基础知识 - JavaScript onerror事件
DEV.OPERA ::使用window.onerror更好地处理错误
窗口onError事件
使用onerror事件来抑制JavaScript错误
SO :: window.onerror没有在Firefox中触发
这对你有帮助吗:
我不确定它如何处理Flash错误...
更新:它在Opera中不起作用,但我现在正在攻击Dragonfly以查看它的内容.关于黑客攻击蜻蜓的建议来自这个问题:
模仿窗口.使用javascript在Opera中的错误
如果您的错误处理非常复杂,因此可能会抛出错误,那么添加一个标志表明您是否已经处于"errorHandling-Mode"状态是很有用的.像这样:
var appIsHandlingError = false; window.onerror = function() { if (!appIsHandlingError) { appIsHandlingError = true; handleError(); } }; function handleError() { // graceful error handling // if successful: appIsHandlingError = false; }
否则你会发现自己陷入了无限循环.
尝试使用Atatus为现代Web应用程序提供高级错误跟踪和真实用户监控.
https://www.atatus.com/
让我解释一下如何在所有浏览器中获得相当完整的堆栈跟踪.
现代Chrome和Opera完全支持ErrorEvent的HTML 5草案规范window.onerror
.在这两种浏览器中,您都可以使用window.onerror
或正确绑定到"错误"事件:
// 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仍然存在,我们也必须支持它们.由于堆栈跟踪不可用,window.onerror
我们必须做更多的工作.
事实证明,我们唯一可以做的就是从错误中获取堆栈跟踪是将所有代码包装在一个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
被改变了.我们只需要在prototype
对象上修复此问题:
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/的网站开发人员.
似乎window.onerror
无法访问所有可能的错误.具体而言,它忽略了:
加载错误(响应> = 400).
加载错误(响应> = 400).
全局错误,如果您的应用程序中有许多其他库也window.onerror
以未知方式操作(jquery,angular等).
可能很多情况下我现在探索之后还没有遇到过(iframe,堆栈溢出等).
以下是捕获许多错误的脚本的开头,以便您可以在开发期间为应用添加更强大的调试功能.
(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等服务以便我们可以在开发期间测量错误以及在分段时进行调试以便我们可以调试正在进行的操作更深层次.然后可以在生产中关闭它.
希望这可以帮助.
// 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;
人们应该保留以前关联的onerror回调