/dev/null [tony lombardo]

Anything and everything ASP.NET and more. Expect to see tips and tricks, opinions on new technology, and fun code samples, along with the occasional rant.
Ending the JavaScript Error Epidemic

I don't know about you, but I'm absolutely tired of getting JavaScript errors on 50% of the websites I visit.  It's pretty much become an expectation that if you visit certain sites (http://www.weather.com comes to mind) you're going to get a JavaScript error.  Why?  Is it because no one cares, or because no one notices?  Either way it's out of control, and it seems that everyone has simply accepted this behavior of the WWW at this point.  Being a web developer my browser is always set to show me JavaScript errors and prompt me to debug.  I do this so that I'm made aware when I introduce a JavaScript error into one of my pages, however it also makes me aware when anyone else does too.  I think it's time that we force a change, and hopefully together we can catalyze this change - turning unhandled JavaScript errors into the exception not the rule.

Do I think that tomorrow everyone will be writing bug free JavaScript ?  Not a chance.  However, I see no reason why web developers can't start being more responsible for their code (bugs).  A couple of months ago I started thinking about global error handling and came up with a prototype.  My original prototype worked by including a JavaScript file in your application, and importing into your page.  The script was pretty straight forward - it added an onerrror event handler to the page in order to capture any unhandled exceptions.  It worked great, and kept errors from bubbling up to the end user.  I view this as the minimum step all web developers should be taking - capturing unhandled events in a deployed application to prevent end users from seeing the error details.  Here's an example of how to trap unhandled exceptions.

function handleErrors(errStr, url, lineNum){ ... }

window.onerror=handleErrors;

 

I said that the above was a minimum because there's more that you can do.. a lot more.  Once you have successfully trapped an error, there's a great deal of information available to help diagnose or debug the problem.  You can even construct a stack trace of your JavaScript functions by using the .caller property of a function prototype.  Here's an example:

function getStackTrace(func){

 

    if(!func)return "";

 

    var trace=getFuncName(func);

    var args="(";

    for(var arg in func.arguments){

        if(args&&args.length&&args.length>1)args+=",";

        args+=func.arguments.toString();

    }

    trace+=args+")\n";

    return trace+getStackTrace(func.caller);

}

At this point we've prevented an error from being surfaced up to the UI and hence prevented a user from being annoyed, and we've also obtained some information about the error by constructing a stacktrace as shown above.  So where do we go from here?  Reporting the error back to the server would be the next step.  There are a couple of different ways you can do this - you can use an HTTP Get using a REST like approach, or you can post the values back to the server and further process the information.  Using an XMLHTTP request, the data can be posted back to the server asynchronously with out interrupting the end user.  I personally like the second technique, because it offers you a high level of flexibility, though it is a bit more work.   

I've decided to take this up as a side project, and create an error handling and reporting mechanism for anyone to use.  I'm not quite ready to publish the code at this point, but I'm hoping to have something ready in the next few weeks. 

Posted: 02 Oct 2007, 15:06
Filed under: ,

Comments

Dale said:

The problem with poorly written javascript on the web is generally attributable to banner ads.  I have taken the time to debug a few of them over the years and have even notified the listed web contact for the host site and the advertiser.  I've never gotten a reply back from either.  They probably thought I was weird to even take the time to figure out what was wrong.

By the way, one of the more common places for me to see such errors (perhaps just based on how I use the Internet) is msdn.microsoft.com.

Dale

# October 3, 2007 6:55 PM

Alan Jackson said:

Hey Tony,

Funny you should mention that.  I see it all the time, especially when popup blockers are enabled.  I think that the biggest offender is the developer who assumes that the popup window will load, and when they try and do something with that popup window, it fails.

# October 4, 2007 1:28 PM

Tony Lombardo said:

Dale, Alan - I agree with both of you, these are the most common places for encountering errors.  The nice thing about adding a global error capture script is that it will actually audit your site for errors based on dynamic content.  For example with many of the banners that are loaded they include html/javascript that can't really be tested since it's all owned and delivered by a 3rd party.  Adding a global error handler can give the web site publisher an idea of who's screwing up their site - something that I would bet is pretty beneficial.  Of course, when that someone is the advertiser paying you $30k a month, I'm sure I can see how some webmasters turn a blind eye.

# October 4, 2007 6:03 PM

Jaap Terlouw said:

Hi Tony,

I can complete agree with it, my point of view is that there are to much developers which are to easy launch a website without proper testing and incorrect development platforms.

Case off course is the companies want to have all for nothing and developers just deliver what they want.

So no guilty as developer wants to get his money and company the site for less.

Not sure if you going to solve this, but my blessing you have,

Jaap

# October 6, 2007 10:19 AM

Philip said:

Hi Tony,

I'm glad someone finally addressed this issue. And you have made an excellent suggestion with source as well. Please keep it up!

I can't understand why the others who have commented here, did not also praise you..... but instead just wanted to add thier two cents worth.... go figure.

This situation is to me a "if you're not part of the solution you are part of the problem" kinda thing. This is every responsible web developers issue. And I hope we can get thru to others.

I will definatly be implementiing your code. Thanks a million! I wish I would have know years ago, that a stack trace was possible in JavaScript... I look forward to the rest of the code.

you might want to publish this when finished on CodeProject. That way, the movement will surely get moving.

# October 10, 2007 3:15 AM

Brilliant.. said:

Once the code is a little more mature, the first thing I'm going to do is write a web service to compile a log of all of the client-side errors that my clients might be receiving, and add this into my master page template.

I care about the errors on my site, whether my users notice them or not.

# October 13, 2007 5:03 PM

Christopher Bishop said:

Ahhhh nothing like bastardized c++ :)

# November 9, 2007 2:09 PM

Barry Solomon said:

Awesome.  Thanks,  this is going to be standard fare for all my sites now.  I took this and wrapped it in a serverside call for Page_Load for anyone who would like to go this route.

Barry

-----------------

public void Javascript_StartupScriptExceptionHandler(Page page)

       {

           string strScript = "<script type='text/javascript'> \n";

           strScript += " function handleErrors(errStr, url, lineNum) \n";

           strScript += " { \n";

           strScript += "   //debugger;\n";

           strScript += "   getStackTrace(handleErrors);\n";

           strScript += " } \n";

           strScript += "  \n";

           strScript += " window.onerror=handleErrors; \n";

           strScript += "  \n";

           strScript += " function getStackTrace(func) \n";

           strScript += " { \n";

           strScript += "  if(!func)return \"\"; \n";

           strScript += "  var trace=getFuncName(func); \n";

           strScript += "  var args=\"(\";\n";

           strScript += "  for(var arg in func.arguments){ \n";

           strScript += "    if(args&&args.length&&args.length>1)args+=\",\"; \n";

           strScript += "    args+=func.arguments.toString(); \n";

           strScript += "    trace+=args+\")\\n\"; \n";

           strScript += "  }\n";

           strScript += "  return trace+getStackTrace(func.caller); \n";

           strScript += "  \n";

           strScript += " } \n";

           strScript += "</script>\n";

           if (!page.ClientScript.IsStartupScriptRegistered("startupScriptExceptionHandler"))

               page.ClientScript.RegisterStartupScript(page.GetType(), "startupScriptExceptionHandler", strScript);

} // end Javascript_StartupScriptExceptionHandler()

# May 2, 2008 3:26 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS