Matt Snider JavaScript Resource

Understanding JavaScript and Frameworks

Saturday, March 29, 2008

Window onError Event

Window.onerror is an obscure and little used event with surprising usefulness. Before the days of FireBug it was difficult to debug, in each browser, where an error occurred and why. Now that we have FireBug, most JavaScript works wonderfully in FireFox and decently in other browsers. And even with the robust debugging, there will still be user machines that were not tested against, who see JavaScript errors that you can never capture. The ‘onerror’ event allows for you to assign a Function to be called every time an error occurs in your JavaScript code, passing into the function the browser message, URL of the current page, and the line number that triggered the error, which improves your ability to debug in any browser. In addition to those benefits, assigning a Function to ‘onerror’, also allows you to prevent errors from bubbling to the browser, and showing those annoying browser popups that occur on JavaScript errors.

Surprisingly this event has been around since IE 4, Netscape 3, and FireFox 1, so it is well supported by current browsers, even though it is rarely used. Here is a simple example of how to use this method:

Example 1: Simple ‘onerror’ Function

// declare this early in your codebase window.onerror = function(message, url, lineNumber) { // code to execute on an error return true; // prevents browser error messages };

Something I am experimenting with is to include this code in a file (”error.js”) right after I initialize my Framework. “error.js” contains my “onerror” listener, catching all errors and exception, which I can then use to send AJAX messages to the back-end to log all JavaScript errors. Moreover, if you use a client detection method (core.js (see Core.Client Object), then you can also log the browser and OS that caused the error. Using YUI connection manager you would do something like:

Example 2: Error Logging

window.onerror = function(message, url, lineNumber) { var params = []; params[0] = ‘browser=’ + Core.Client.browser; params[1] = ‘data=’ + navigator.userAgent + ‘|’ + navigator.vendor + ‘|’ + navigator.platform; params[2] = ‘lineNumber=’ + Core.Client.message; params[3] = ‘message=’ + Core.Client.lineNumber; params[4] = ‘os=’ + Core.Client.OS; params[5] = ‘url=’ + Core.Client.url; params[6] = ‘version=’ + Core.Client.version; try { YAHOO.util.Connect.asyncRequest(’GET’, ‘logJavaScriptError.event?’ + params.join(’&'), function() {}, null); } catch(e) { // squelch, because we don’t want to prevent method from returning true } return true; };

In this case you are logging the line number, url, and browser error message, in additional to client information. I also go ahead and send all possible browser variables, for future parsing in case I could not properly discern the browser programatically. The AJAX request, is simply a fire-and-forget pattern, because we don’t really care if it is successful or not, we assume that 99% of the time it will succeed, so that these errors are properly logged. If there is an exception thrown in the AJAX code, say by YUI because the URL is not found, then this method would not completely execute. However, if you wrap the AJAX in a try/catch, you can ensure that the end of the method is reached and ‘TRUE’ is returned, to prevent errors from being shown to the browser.

I have created a test page, which tries to use a non-existant variable, thereby throwing an error. One thing you’ll probably notice is that you don’t get that pesky JavaScript error message in IE, however, you also do not get any FireBug goodness in FireFox. For FireBug to detect errors, the error must be allowed to bubble to the browser, so you will probably want a constant to turn off/on a debug mode, so that you can still use FireBug for development.

I also played around with using Framework Event handlers, however, none of the Frameworks I tested (YUI, MooTools, and Prototype) special-case an event handler for “window.onerror”. There are two problems with “window.onerror” that requires special-case event handling. The first problem is that when using event handlers, the callback Function will only be passed the Event Object, instead of the 3 parameters that should be passed. Second, returning ‘TRUE’ does not stop the error (as the callback Function is wrapped), nor does stopping propagation and/or bubbling, so you cannot prevent errors from bubbling to the browser. You will have to assign your error handling method, directly to “window.onerror”, and replace any implementation that your Framework might use.

Fortunately, after doing a quick search through those sample Frameworks, I found that only YUI attempts to implement the “window.onerror” code, and only in their “logger.js” file. In the definition of the Logger Object, you can specify whether to use an ‘onerror’ callback or not. I believe then, it is relatively safe, to play around with this event.

posted by Matt Snider at 6:38 pm  

3 Comments »

  1. JavaScriptMVC’s Error plugin overrides the onerror event, using it to send a message to a free email notification service. Its used to let you receive an email whenever someone encounters an error in your web pages.

    http://javascriptmvc.com/learningcenter/error/index.html

    The code is open source.

    Comment by Brian Moschel — March 30, 2008 @ 7:28 am

  2. Oh, I forgot to mention that one problem with onerror is that Safari and Opera don’t support it. So be careful with putting any crucial application functionality in an onerror handler, it won’t work for a percentage of your users. For those browsers you have to rely on try…catch blocks.

    Comment by Brian Moschel — March 30, 2008 @ 7:30 am

  3. If you have to worry about cross-domain related issues related to XHR use the Image object with URL encoded query string parameters.

    See:
    http://blogs.splunk.com/carl/2008/01/16/javascript-error-logging-with-splunk/

    Comment by Carl S. Yestrau — July 8, 2008 @ 5:59 pm

RSS feed for comments on this post. TrackBack URI

Leave a comment

Powered by WordPress