JavaScriptexception处理
捕获JavaScript中引发的所有exception的最佳技术是什么?
显然,最好的方法是使用try … catch。 但是,如果使用asynchronouscallback等等,那可能会变得棘手。
我知道IE和Gecko浏览器支持window.onerror,但是Opera和Safari呢?
下面是一些testing用例,我希望有一个中央exception处理解决scheme:
// ErrorHandler-Test1 var test = null; test.arg = 5; // ErrorHandler-Test2 throw (new Error("Hello")); // ErrorHandler-Test3 throw "Hello again"; // ErrorHandler-Test4 throw { myMessage: "stuff", customProperty: 5, anArray: [1, 2, 3] }; // ErrorHandler-Test5 try { var test2 = null; test2.arg = 5; } catch(e) { ErrorHandler.handleError(e); } // ErrorHandler-Test6 try { throw (new Error("Goodbye")); } catch(e) { ErrorHandler.handleError(e); } // ErrorHandler-Test7 try { throw "Goodbye again"; } catch(e) { ErrorHandler.handleError(e); } // ErrorHandler-Test8 try { throw { myMessage: "stuff", customProperty: 5, anArray: [1, 2, 3] }; } catch(e) { ErrorHandler.handleError(e); }
如果您想到其他任何testing用例,请提及它们。 其中几个例子提到了一个ErrorHandler.handleError方法。 这只是使用try … catch时的build议指南。
如果您使用像jQuery这样的库来分配所有事件处理程序,那么可以使用window.onerror
和包装jQuery事件处理程序代码的组合,并在就绪函数中添加error handling函数(请参阅: JavaScript错误跟踪:为什么window.onerror还不够 )。
-
window.onerror
:捕获IE中的所有错误(以及Firefox中的大多数错误),但在Safari和Opera中不做任何事情。 - jQuery事件处理程序:捕获所有浏览器中的jQuery事件错误。
- jQuery就绪函数:捕获所有浏览器中的初始化错误。
WebKit(Safari,Chrome等)现在似乎支持onerror
。
原文:据我所知,WebKit / Safari不支持onerror
事件。 这是一个该死的耻辱。
其实,jQuery的方法并不是那么糟糕。 看到:
http://docs.jquery.com/Events/error#fn
和:
$(window).error(function(msg, url, line){ $.post("js_error_log.php", { msg: msg, url: url, line: line }); });
用自己的exception处理程序捕获所有exception,并使用instanceof。
$("inuput").live({ click : function (event) { try { if (somethingGoesWrong) { throw new MyException(); } } catch (Exception) { new MyExceptionHandler(Exception); } } }); function MyExceptionHandler(Exception) { if (Exception instanceof TypeError || Exception instanceof ReferenceError || Exception instanceof RangeError || Exception instanceof SyntaxError || Exception instanceof URIError ) { throw Exception; // native error } else { // handle exception } }
因为没有try-catch块,MyExcetpionHandler会抛出本地错误。
访问http://www.nczonline.net/blog/2009/03/10/the-art-of-throwing-javascript-errors-part-2/
try-catch
并不总是最好的解决scheme。 例如,在Chrome 7.0中,在控制台窗口中会丢失漂亮的堆栈跟踪。 重新审视exception并没有帮助。 我不知道任何解决scheme,保留堆栈跟踪,让你对exception作出反应。
通过一些工作,可以在所有浏览器中获得相当完整的堆栈跟踪。
现代的Chrome和Opera(即基于Blink渲染引擎的任何东西)完全支持HTML 5草案的ErrorEvent和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 // sendData(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 // sendData(data); })
不幸的是,Firefox,Safari和IE还在,我们也必须支持他们。 由于在window.onerror
没有可用的堆栈跟踪,我们必须做更多的工作。
事实certificate,我们唯一能做的就是将所有的代码包装在一个try{ }catch(e){ }
块中,然后看看e.stack。 我们可以通过一个叫wrap的函数来简化这个过程,这个函数接受一个函数并返回一个新的函数,并且具有良好的error handling能力
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 // sendData(data); throw e; } } } return func._wrapped; };
这工作。 你手动包装的任何函数都会有很好的error handling。
您可以使用图像标签发送数据如下
function sendData(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; }
但是,你必须做后端来收集数据和前端来可视化数据。
在阿塔图斯 ,我们正在解决这个问题。 Atatus不仅仅是错误跟踪,还提供真正的用户监控。
免责声明:我是Atatus的网页开发人员。
确实,在现代浏览器中,将window.onerror挂接到顶部的错误以及为Ajax错误添加jQuery事件处理程序将会捕获抛出客户端代码中的所有Error对象。 如果你手动设置window.onerror的处理程序,在现代浏览器中,这是用window.addEventListener('error', callback)
,而在IE8 / 9中,你需要调用window.attachEvent('onerror', callback)
。
请注意,您应该考虑处理这些错误的环境,以及这样做的原因。 捕获堆栈跟踪尽可能多的错误是一回事,但现代F12开发工具的出现解决了本地实现和debugging时的这种用例。 断点等将给你更多的数据比处理程序可用,特别是从CORS请求加载的第三方库引发的错误。 您需要采取额外的步骤来指导浏览器提供这些数据。
关键问题是在生产环境中提供这些数据,因为您的用户可以保证运行的浏览器和版本数量远远超过您可能testing的数量,而且无论您投入多lessQA,您的网站/应用程序都会以意想不到的方式崩溃它。
为了处理这个问题,你需要一个生产错误跟踪器,它会在你的用户的浏览器中使用你的代码时发现每一个错误,然后把它们发送到你可以查看数据的端点,并用来修复错误。 在Raygun(免责声明:我在Raygun工作),我们已经付出了一大笔努力,为此提供了一个很好的经验,因为有许多陷阱和问题需要考虑,一个幼稚的实现将错过。
例如,你可能会捆绑和缩小你的JS资源,这意味着从缩小的代码抛出的错误将具有破坏variables名称的垃圾堆栈跟踪。 为此,您需要使用构build工具来生成源映射(我们build议使用UglifyJS2来pipe理这部分stream程),然后使用错误跟踪器来接受并处理这些源映射,从而将损坏的堆栈轨迹转换为可读的轨迹。 Raygun完成了所有这些工作,并且包含一个API端点,用于在构build过程中生成源地图。 这是关键,因为他们需要保持非公开,否则任何人都可以unminify你的代码,否定它的目的。
raygun4js客户端库还为现代和旧版浏览器提供了window.onerror
,以及jQuery钩子,所以设置这个只需要添加:
<script type="text/javascript" src="//cdn.raygun.io/raygun4js/raygun.min.js" </script> <script> Raygun.init('yourApiKey').attach(); </script>
还有一些内置的function,包括在发送错误有效载荷之前进行变异,添加标签和自定义数据以及查看错误的用户的元数据。 它也从上面提到的第三方CORS脚本中获得良好的堆栈跟踪,解决了可怕的“脚本错误”(不包含错误消息,没有堆栈跟踪)。
更重要的问题是,由于networking上的大量观众,您的网站将产生成千上万的每个错误的重复实例。 像Raygun这样的错误跟踪服务可以将这些错误跟踪到错误组,所以你不会淹没在大量的通知中,让你看到每个实际的错误都可以被修复。
我也在寻找error handling和堆栈跟踪和logging用户操作这是我发现希望这也可以帮助你https://github.com/jefferyto/glitchjs