This post originated from an RSS feed registered with Ruby Buzz
by .
Original Post: What Went Wrong with my Javascript?
Feed Title: cfis
Feed URL: http://cfis.savagexi.com/articles.rss
Feed Description: Charlie's Blog
Latest Ruby Buzz Posts
Latest Ruby Buzz Posts by
Latest Posts From cfis
Advertisement
Now that you've launched your new killer Web 2.0 website, how do you detect errors in your deployed Javascript?
Using onerror
The standard approach is to hook into the Window object's onerror event handler and use Ajax to log your requests to the server. There are some good tutorials on the web on how to do this, but here is one approach:
// Register global error handler
window.onerror =function(message, uri, line){var fullMessage = message +"\n at "+ uri +": "+ line
remoteLogger.log(fullMessage)
// Let the browser take it from herereturnfalse}
Notice that you have to explicity set window.onerror using old-style event handlers, attachEvent and addEventListener don't seem to do the trick. Also, Internet Explorer always stupidly sets the URI parameter to the URI of the current page, not the file that caused the problem. Thus you have to hunt through all the linked Javascript files looking at the specified line number and make a best guess as to which file caused the problem.
Getting a Stack Trace
Often times knowing where an error occurred is not enough - what you really need is the full stack trace. If your user has a Gecko based browser (eg, Firefox), you're in luck.
Notice the stack parameter in the code above? Gecko has a poorly documented stack property on the global Error object that provides just what we need.
Let's say you have code that looks like this:
functionfirst(){second()}
second =function(){blowUp()}functionblowUp(){try{
foo.bar()}catch(e){handleException(e)}}
If you call the first method, say from onload like in this example, the resulting stack trace is:
Notice that the method_name will be blank for anonymous functions, which are quite common if you follow the prototype javascript style.
A Simple Logger
Now let's take a look at some code. First, here is a simple logger that posts errors to a server via Ajax (note this code assumes your are using the prototype library):
Next, let's define the handleException method we used above. This method extracts out useful information from an Error object and uses the logger above to post the results to a server.
functionhandleException(exception){/* In FF exception can be a string if it happens when opening the xmlHttpRequest. Gah! */if(typeof exception =='string')
exception =newError(exception)/* If a xmlhttp request is happening in Mozilla and the user navigates to another page, then when the first request returns a NS_ERROR_NOT_AVAILABLE error will be thrown. So just ignore it. */if(exception.name =='NS_ERROR_NOT_AVAILABLE')returnvar fullMessage =''var uri =''var stack =''var line =''try{/* Don't use exception.toString since the JS spec does not require it to provide the error name or message (haven't tested to see if it matters though across browsers) */
fullMessage = exception.name +': '+ exception.message
uri = exception.fileName
stack = exception.stack
// Firefox sometimes blows up here
line = exception.lineNumber
}catch(e){}
fullMessage +="\n at "+ uri +": "+ line
console.info(fullMessage)
console.info(stack)
remoteLogger.log(fullMessage, stack)}
Annoying Gotchas
There are few annoying gotchas to know about:
Stack traces are only available from Error objects thrown by exceptions and thus are not available from the onerror method.
Uncaught exceptions are not hanlded by onerror.
There is no global exception handler in Javascript, so you have to be very careful in the way you right your code. On the positive side, its easy to implement a global error handler for methods that are invoked due to the results of an Ajax request. On the other hand, its much harder to do this for methods invoked due to normal events generated by a user interacting with the browser.
Anyway, the more information you can get about browser errors the better - you'll often be surprised by the results!