JSAPI capturing errors in application and making debugging difficult

1712
8
08-26-2013 09:48 AM
BryanBaker
Occasional Contributor
In recent versions of the JavaScript API (at least the compact version, here v. 3.6), the minified JSAPI is catching/capturing errors within my own JavaScript code. The result is that I see errors in the browser error console, but I cannot track down where the error is coming from. For example, today I saw an error in the console (here Google Chrome's console) of "TypeError", with a message of "undefined is not a function". That's it - no further error information or stack trace.

The console points to a location in the JSAPI. I used Chrome's "pretty print" function ("{}" at the bottom of the console) to try to track down the error source, by adding a break point at the line identified (in this case, line 1869). But when I trip the offending code and hit the break point, the Call Stack only points to lines internal to the JSAPI.

I eventually tracked down my error, which had nothing to do with the JSAPI itself - it was just that I had used 'this' assuming it referenced my custom object when it actually pointed to the window object. I see no reason that the JSAPI should be catching this kind of error.

Is there any way to prevent the JSAPI from catching all errors in code outside the JSAPI itself? I'm sure I could add try/catch JavaScript blocks, but that's impractical to do in every single function or code block during development.

BY THE WAY, I DO NOT WORK FOR ESRI. I did up until 2009, but the Forum website administrator has ignored my repeated requests to remove the ESRI logo from my posts.
0 Kudos
8 Replies
JasonZou
Occasional Contributor III
I am afraid that trying to catch the errors in your code would be the only way to prevent the error handled in JSAPI. Javascript exception handling is much similar to the way designed in OOP languages. When an exception occurs, it will try to be processed inside the code block where the exception is generated. If not, it will flow up along its invocation chain to the upper level until it's been processed. If no code is to capture the exception, the default handler will take into place.

I agree that it is very annoying when the exception is captured in JSAPI. But it's better to get informed something wrong in the code than ignoring the errors.

I would love to know there is a better way:)
0 Kudos
KenBuja
MVP Esteemed Contributor
Take a look at the video from a session at the 2013 Developers Summit called "Debugging Applications Built with ArcGIS API for JavaScript" (there's also the powerpoint slides to go with it, but it only contains 9 slides).

Go to about 40:00 mark where Derek talks about this. Unfortunately, he doesn't have much to say about this, except examine your code.
0 Kudos
BryanBaker
Occasional Contributor
Thanks for the comments. Ironically, I was in the audience at the 2013 Dev Summit session on debugging, and asked the first question as a follow up to that section on error handling. There wasn't a good answer there, as you point out.

The frustrating thing about this is that back several versions ago, maybe around 2.3 or so, this was not the behavior of the JSAPI. If an error occurred in my code, I would see the browser error console pointing to that line in my code, not to an obscure error handler inside the minified JSAPI. I'm guessing some change was made to the JSAPI that causes it to capture all errors, at least any that happen after you've called some function in the API.
0 Kudos
BryanBaker
Occasional Contributor
A follow up on this. The JS API is definitely trapping any errors downstream from callbacks. So any code you run following a callback will have any errors trapped by the JS API handler. zj_zou is correct that it's normal for errors to follow the call stack until a handler is found, if any. But my complaint is that the JS API simply shuts up the error without any notification. It's like doing this in C#:

try {
   double oops = 1/0;
}
catch (Exception ex)
{
}

...so nothing is done with the error. The result is that your code mysteriously fails - either nothing happens or you get unexpected results, with no information or clue about where or what went wrong.

I've now started wrapping code inside my callback functions with try-catch JS blocks. I actually created a central function to which I send errors, which prints information to the console, along these lines:

handleError: function (err) {
   var msg = "JS error caught by handleError:\r\n" + err.message;
   for (var prop in err) {
        if (prop !== "popStackFrame")
            msg += "\r\n" + prop + ": " + err[prop].toString();
    }
    console.log(msg);
}


Firebug and IE10's console do the best with this: both show the line number where the original error occurs (IE even provides a stack trace - not bad, IE). Chrome only shows a simple message.

It would be really helpful if the JS API would do something like this when it handles errors.
0 Kudos
JasonZou
Occasional Contributor III
Excellent point, Brian. I will definitely give it a try. You have my vote!
0 Kudos
KenBurcham
Occasional Contributor
I agree and found the swallowing of errors a difficult and frustrating problem as I've been learning Javascript and JSAPI. 

I've ended up doing the same strategy when something is just quietly failing, I find and wrap the code (once I figure out where it might be dying!) with a try/catch block and pass the exception to my error handler.  It would be GREAT if ESRI added a noisy default error handler, at least in some kind of a debug mode.

I guess this is basically a worthless "me too" post, but at least I feel better. 🙂

thanks,

ken.
0 Kudos
JasonScharf
New Contributor III
I believe that Dojo's Deferred and DeferredList objects are what trap exceptions. The purpose of that would be to manage to satisfy deferred promises even when things go really sideways. It does make debugging trickier.

Wrapping your code and trapping exceptions with your own blocks is a workable strategy. You can also use setTimeout with a timeout of 0 to "hoist" your methods out of the try/catch blocks that Dojo executes callbacks in.

An even better method is to use Chrome's exception handling. If you open the F12 developer tools and navigate to the "Sources" tab, there is a little octagonal pause button in the lower left. Clicking it will allow you to pause on unhandled exceptions or all exceptions. Pausing on all exceptions will pause at the throw site of the exception, which is invaluable in our scenario.

You can also do this in IE with Visual Studio. I'm currently on VS 2012. In the "DEBUG" menu, there is an "Exceptions" option. In the Exceptions window, you can tick off the "Thrown" option in the column next to JavaScript Runtime Exceptions. This will break at throw sites, just like Chrome does.

Hope this helps!
0 Kudos
JonathanUihlein
Esri Regular Contributor
Jason, thank you so much for your post.
I was wondering why this happened and you have made it very clear.

+1
0 Kudos