Attention: We are retiring the ASP.NET Community Blogs. Learn more >

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. 

6 Comments

  • Yes, JavaScript errors are centainly annoying for a web developer! Sometimes I have to browse with Firefox on especially buggy sites.

  • You're right about the epidemic. Web pages are too fragile when it comes to JavaScript code.

  • You may want to research Javascript caller callee recursion. The code as you have written can easily get stuck in an infinite loop. Try setting a counter so this doesn't happen. You also need to understand that the stacktrace you get back - may not exactly be how the code executed. Try running the following example for illustration

    Example:
    foo1(false);

    function foo1(isFoo2)
    {
    if(isFoo2)
    makeanErrorHere();
    else
    foo2(true);

    }

    function foo2()
    {
    foo1(true);
    }

    //your stack trace will look like this...
    /*
    Object expected foo1('true') foo2() foo1('true') foo2() foo1('true') foo2() foo1('true') foo2() foo1('true') foo2()......
    You can find some links online that explain why the trace isn't really the current state of a function as it was executed.
    */

  • Thanks for the advice Dave - having a maxdepth when dealing with recursion is always a good idea. I wasn't aware of the limitation of the caller callee that you mentioned so I'll certainly read up on that. The main point of the post still stands though - trapping errors and collecting information is possible and easy enough that there's no reason not to (even with a slightly incorrect stack trace :) )

  • I'm also getting javascript errors. Also I can no longer use Internet Explorer-it freezes on me.

  • The backtrace stuff is fun, but in Mozilla (as opposed to IE) you can't use it from window.onerror. Very frustrating! I've been trying to find a way to access this information, but it appears to be completely unavailable.

    Perhaps IE calls the onerror function immediately, so the backtrace is valid, whereas Mozilla pops up the stack, destroying the information in the process?

Comments have been disabled for this content.