JavaScript Exception Handling - javascript

What is the best technique for catching ALL exceptions thrown within JavaScript?
Obviously, the best technique is to use try...catch. But with ansynchronous callbacks and so forth, that can get tricky.
I know IE and Gecko browsers support window.onerror, but what about Opera and Safari?
Here are a bunch of test-cases that I would like to have a central exception handling solution for:
// ErrorHandler-Test1
var test = null;
test.arg = 5;
// ErrorHandler-Test2
throw (new Error("Hello"));
// ErrorHandler-Test3
throw "Hello again";
// ErrorHandler-Test4
throw {
myMessage: "stuff",
customProperty: 5,
anArray: [1, 2, 3]
};
// ErrorHandler-Test5
try {
var test2 = null;
test2.arg = 5;
} catch(e) {
ErrorHandler.handleError(e);
}
// ErrorHandler-Test6
try {
throw (new Error("Goodbye"));
} catch(e) {
ErrorHandler.handleError(e);
}
// ErrorHandler-Test7
try {
throw "Goodbye again";
} catch(e) {
ErrorHandler.handleError(e);
}
// ErrorHandler-Test8
try {
throw {
myMessage: "stuff",
customProperty: 5,
anArray: [1, 2, 3]
};
} catch(e) {
ErrorHandler.handleError(e);
}
If you think of any other test-cases, please mention them. Several of these cases mention a ErrorHandler.handleError method. This is just a suggested guideline when using try...catch.

If you use a library like jQuery for assigning all your event handlers, you can use a combination of window.onerror and wrapping the jQuery event handler code and on ready function with an error handling function (see: JavaScript Error Tracking: Why window.onerror Is Not Enough).
window.onerror: catches all errors in IE (and most errors in Firefox), but does nothing in Safari and Opera.
jQuery event handlers: catches jQuery event errors in all browsers.
jQuery ready function: catches initialisation errors in all browsers.

WebKit (Safari, Chrome, etc) now appears to support onerror.
Original post: As far as I know, WebKit/Safari does not support the onerror event. Which is a damn shame.

Actually, the jquery approach isn't so bad. See:
http://docs.jquery.com/Events/error#fn
and:
$(window).error(function(msg, url, line){
$.post("js_error_log.php", { msg: msg, url: url, line: line });
});

Catch all exceptions with your own exception handler and use instanceof.
$("inuput").live({
click : function (event) {
try {
if (somethingGoesWrong) {
throw new MyException();
}
} catch (Exception) {
new MyExceptionHandler(Exception);
}
}
});
function MyExceptionHandler(Exception) {
if (Exception instanceof TypeError ||
Exception instanceof ReferenceError ||
Exception instanceof RangeError ||
Exception instanceof SyntaxError ||
Exception instanceof URIError ) {
throw Exception; // native error
} else {
// handle exception
}
}
MyExcetpionHandler will throw native error as there is no try-catch block.
Visit http://www.nczonline.net/blog/2009/03/10/the-art-of-throwing-javascript-errors-part-2/

try-catch is not always the best solution. For example, in Chrome 7.0 you lose the nice stack trace in the console window. Rethrowing the exception does not help. I don't know of any solution which preserves stack traces and letting you react on exception.

With a little bit of work it's possible to get stacktraces that are reasonably complete in all browsers.
Modern Chrome and Opera (i.e. anything based around the Blink rendering engine) fully support the HTML 5 draft spec for ErrorEvent and window.onerror. In both of these browsers you can either use window.onerror, or (amazingly!) bind to the 'error' event properly:
// Only Chrome & Opera pass the error object.
window.onerror = function (message, file, line, col, error) {
console.log(message, "from", error.stack);
// You can send data to your server
// sendData(data);
};
// Only Chrome & Opera have an error attribute on the event.
window.addEventListener("error", function (e) {
console.log(e.error.message, "from", e.error.stack);
// You can send data to your server
// sendData(data);
})
Unfortunately Firefox, Safari and IE are still around and we have to support them too. As the stacktrace is not available in window.onerror we have to do a little bit more work.
It turns out that the only thing we can do to get stacktraces from errors is to wrap all of our code in a try{ }catch(e){ } block and then look at e.stack. We can make the process somewhat easier with a function called wrap that takes a function and returns a new function with good error handling.
function wrap(func) {
// Ensure we only wrap the function once.
if (!func._wrapped) {
func._wrapped = function () {
try{
func.apply(this, arguments);
} catch(e) {
console.log(e.message, "from", e.stack);
// You can send data to your server
// sendData(data);
throw e;
}
}
}
return func._wrapped;
};
This works. Any function that you wrap manually will have good error handling.
You can send data using image tag as follows
function sendData(data) {
var img = newImage(),
src = http://yourserver.com/jserror + '&data=' + encodeURIComponent(JSON.stringify(data));
img.crossOrigin = 'anonymous';
img.onload = function success() {
console.log('success', data);
};
img.onerror = img.onabort = function failure() {
console.error('failure', data);
};
img.src = src;
}
However you have to do backend to collect the data and front-end to visualise the data.
At Atatus, we are working on solving this problem. More than error tracking, Atatus provides real user monitoring.
Give a try https://www.atatus.com/
Disclaimer: I am a web developer at Atatus.

It is true that with modern browsers, hooking window.onerror for errors that bubble all the way to the top along with adding jQuery event handlers for Ajax errors will catch practically all Error objects thrown in your client code. If you're manually setting up a handler for window.onerror, in modern browsers this is done with window.addEventListener('error', callback),
while in IE8/9 you need to call
window.attachEvent('onerror', callback).
Note that you should then consider the environment in which these errors are being handled, and the reason for doing so. It is one thing to catch as many errors as possible with their stacktraces, but the advent of modern F12 dev tools solves this use case when implementing and debugging locally. Breakpoints etc will give you more data than is available from the handlers, especially for errors thrown by third-party libraries which were loaded from CORS requests. You need to take additional steps to instruct the browser to provide this data.
The key issue is providing this data in production, as your users are guaranteed to run a far wider array of browsers and versions than you can possibly test, and your site/app will break in unexpected ways, no matter how much QA you throw at it.
To handle this, you need a production error tracker which picks up every error thrown in your user's browsers, as they use your code, and sends them to an endpoint where the data can be viewed by you and used to fix the bugs as they happen. At Raygun (disclaimer: I work at Raygun) we've put a bunch of effort into providing a great experience for this, as there's many pitfalls and issues to consider that a naive implementation will miss.
For instance, chances are you'll be bundling and minifying your JS assets, which means that errors thrown from minified code will have junk stacktraces with mangled variable names. For this, you need your build tool to generate source maps (we recommend UglifyJS2 for this part of the pipeline), and your error tracker to accept and process these, turning the mangled stacktraces back into human-readable ones. Raygun does all this out of the box, and includes an API endpoint to accept source maps as they are generated by your build process. This is key as they need to be kept non-public, otherwise anyone could unminify your code, negating its purpose.
The raygun4js client library also comes with window.onerror for both modern and legacy browsers, as well as jQuery hooks out-of-the-box, so to set this up you only need to add:
<script type="text/javascript" src="//cdn.raygun.io/raygun4js/raygun.min.js" </script>
<script>
Raygun.init('yourApiKey').attach();
</script>
There's also a bunch of functionality built-in including the ability to mutate the error payload before it is sent, adding tags and custom data, metadata on the user who saw the error. It also takes the pain out of getting good stack traces from the above-mentioned third-party CORS scripts, which solves the dreaded 'Script Error' (which contains no error message, and no stack trace).
A more crucial issue is that due to the huge audience on the web, your site will generate many thousands of duplicate instances of each error. An error tracking service like Raygun has smarts to roll these up into error groups so you don't drown in a flood of notifications, and lets you see each actual error ready to be fixed.

I was also looking for error handling and stacktrace and logging for user actions this is what i found hope this also helps you
https://github.com/jefferyto/glitchjs

Related

JS - how to prevent script from stopping after thrown error

How can I prevent the script from stopping after an error has been thrown? Is there something like exception handling in JS?
Console text
Not allowed to load local resource: file:///C:/Users/Temp/image.png
Javascript does have exception handling. There are two possible types of error you can encounter:
1) Places in your application where you proactively guard against errors being thrown, for example, AJAX request. You can handle them like this:
try {
AJAX-code or other code susceptible to errors
} catch(error){
// Log error
}
2) Script errors or compile-time error, for example, undefined variables. In browsers, window.onerror is a global event handler which is called on script or compile errors. However, it's implementation is inconsistent across browsers. You can use it like this:
window.onerror = function(message, url, lineNo) {
// Code to handle the error
}
The main problem with onerror is that no stack trace is passed through which is not very helpful. However, Chromium has added column number and errorObj, so hopefully other browsers will implement the same in near future.
There surely is: try {} catch (exception) {}
Sure, wrap your code inside try/catch:
try
{
//Run some code here
}
catch(err)
{
//Handle errors here
}
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch
You can use a try/catch/finally block to handle errors:
try {
// Whatever you need
} catch(error) {
// Handle error if one occurs
} finally {
// Last resort
}
Note that you can have multiple catch blocks in-between your try and finally as needed.
Here's some more information.

Find where a syntax error occurs when new Function() fails

To shortcut a long comment section on "don't use new Function" and/or "eval is evil", this question is about how to access, if possible, error information that is related to a new Function() constructor failing. It's mostly a question to discover a limit in what the browser will let me do when trying to exploit JavaScript to the extent that the spec and standard browser implementations allow. So with that disclaimer in place:
When evaluating code through a new Function() call, is there a way to find out where in the function's content a syntax error occurs, if illegal-syntax code is being evaluated? i.e.:
try {
var generator = new Function(input);
try {
generator();
}
catch (runtimeError) {
console.error("legal code; unforeseen result: ", runtimeError);
}
}
catch (syntaxError) {
console.error("illegal code; syntax errors: ", syntaxError);
}
When the building of the generator fails, is there a way to find out (from the browser, not using jslint or another external library) what the error was or where it occurred?
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SyntaxError/prototype mentions that a SyntaxError has a filename and linenumber property, but these are undefined for dynamic code evaluated through a new Function() constructor from what I can tell, so relying on the error object itself seems not to be an option. Are there alternative ways to introduce the code to the browser so that the code, once we know it has syntax errors from a failing new Function call, can be used to find out where the problem is according to the JS engine used?
(Of course, if the goal was to simply find syntax errors, jslint as a preprocess step would be the go-to solution, but I'm more interested in whether or not browsers can in some way be made to report this information, even if in limited form like "there is SOME error on line/char ...")
afaik impossible to find out where it occured. but you may want to see Exception.message to fetch information what the error was.
example: http://jsbin.com/IRoDiJIV/1/watch?js
Found a solution myself using a simiar method to setting breakpoints in evaled code
In chrome dev tools's sources panel, I put the following in a conditional breakpoint on the new Function line (since it's library code and I can't change it.)
(function(eval_js, load_js) {
try {
eval(eval_js);
} catch (e) {
(function addCode(js) {
var e = document.createElement('script');
e.type = 'text/javascript';
e.src = 'data:text/javascript;charset=utf-8,' + escape(js);
document.body.appendChild(e);
console.warn("Inserted Script for ", js);
})(load_js.replace(/;/g,";\n"));
handlerCode = "";
return false;
}
return false;
})("new Function('event', handlerCode)", handlerCode)

silent javascript errors

This may be a bad question, but I've noticed that as I'm writing coding along using mootools When I've got some code that goes through callbacks, bindings and generally isn't just a straight forward function call, if there's an error it doesn't get picked up by either Firebug or Chrome's console it just silently fails, and I'm forced to track down the error using trys and such that don't give you handy information like the line of code that's failing. It's like writing code for IE6 all you have to go on is some opaque message like 'can not read 'x' of undefined.'
I realize that the question isn't specific enough to ask 'how do I avoid this' but does anyone else run into this problem and if so how do you work around it? I'm also a little confused how an error could be picked up by a try/catch block, but not the javascript console.
EDIT:
OK, I've come up with something that reproduces the error
say you've got a function
function foo(){
var x = value.blah;
}
if I call that function like foo() I rightly get an reference error in my console. If, however, I call it like
(function(){
foo.attempt();
})()
I get no error in the console, but if I change foo to be
function foo(){
try{
var x = value.blah;
} catch(e){console.log(e)}
}
the console will log e but of course without the handle 'line: whatever' information.
I have considerable experience fiddling with errors in JavaScript. I've mostly used Chrome for building my understanding but most of it applies to Firefox and Internet Explorer as well.
I can immediately debunk your assumption about silent JavaScript errors. They don't exist, Errors always show. There might be a bug in Firefox or the Chrome's webdev, but the errors are there.
The most common way for errors not to show up is because you're catching them yourself. Perhaps prematurely.
I've figured out what I think is the best strategy for catching errors:
1. Always throw things that are Errors or inherited from Errors.
Ex: not: throw "Precondition failed" but throw new Error("Precondition failed").
This is because Errors are weird in JavaScript (I have no other word for it). If you want a stacktrace (and heaven's yes you want a stacktrace) you'll need to throw an Error (and not a string).
2. Don't use window.onerror Not much to say here. It's useless. You have no control over what get's flung to this function. It might be your code, it might be a broken plugin that a visitor uses. Also, no stacktrace.
3. Have one (global) error handler / when to catch errors
JavaScript is event driven. This has some unexpected consequences. Observe the following code:
try {
setTimeout(function () {
throw new Error("nope! :D");
}, 1);
} catch (e) {
console.log(e);
}
You will not see this error. (Firebug / console will catch it though)
This is because the inner function runs in it's own event and the try-catch statement no longer applies to it. The correct way is:
try {
setTimeout(function () {
try {
throw new Error("nope! :D");
} catch (e) {
console.log("Hell yea!", e);
}
}, 1);
} catch (e) {
console.log(e);
}
Or just make a function that wraps a function in a try-catch:
function wrap(wrap_dat_func) {
return function () {
try {
wrap_dat_func.apply(wrap_dat_func, arguments);
} catch (e) {
// send to error handler
}
}
}
Use like:
setTimeout(wrap(function () {
// etc
}), 1);
So basically whenever you generate a new event, wrap the callback in your global try catch function. So wrap call to setTimeout, setInterval all DOM related events like onclick onload ondocumentready, also AJAX calls onreadystatechanged.
How to get proper stacktraces (over events!) is another long winded explanation.

Get the actual Javascript Error object with window.onerror

Javascript has this great callback window.onerror. It's quite convenient to track any error. However, it calls with the error name, the file name and the line. It's certainly not as rich as getting the actual error object from a try...catch statement.
The actual error object contains a lot more data, so I am trying to get that. Unfortunately, try...catch statement do not work fine when you start having async code.
Is there a way to combine and get the best of both worlds? I initially looked for a way to get the last error triggered within an onerror block, but it looks like JS doesn't store that.
Any clue?
this is now possible in some browsers.
The spec was updated to include the actual error with stacktrace as the 5th parameter.
the problem is that not every browser supports this yet, so you could do something like this:
window.onerror = function(message, filename, lineno, colno, error)
{
if(error != null)
{
//handle the error with stacktrace in error.stack
}
else
{
//sadly only 'message', 'filename' and 'lineno' work here
}
};
If you're referring to stack trace of the error object, then AFAIK, this is not possible.
Simple reason being that a stack trace is related to an execution context in which runtime exceptions (handled with try...catch...finally) were created or thrown (with new Error() or throw).
Whereas when window.onerror is invoked, it is called within a different context.
You can get some mileage by inspecting window.event (not available on FF) in your onerror handler.
Modern browsers fully support the HTML 5 draft spec for ErrorEvent and window.onerror. In both of these browsers you can either use window.onerror, or (amazingly!) bind to the 'error' event properly:
// Only Chrome & Opera pass the error object.
window.onerror = function (message, file, line, col, error) {
console.log(message, "from", error.stack);
};
// Only Chrome & Opera have an error attribute on the event.
window.addEventListener("error", function (e) {
console.log(e.error.message, "from", e.error.stack);
});

javascript error and exception handler

is it possible to register an error or exception handler/function that will be executed when a javascript error or exception occurs? I just feel wrapping all codes in try/catch block seems very tedious and inefficient.
window.onerror = function (msg, file, line) {
// handle error here
}
Supported by:
Chrome 13+
Firefox 6.0+
Internet Explorer 5.5+
Opera 11.60+
Safari 5.1+
Andy E's answer (+1) tells you how to do it.
That said, JavaScript isn't really meant to have caught execeptions in the same sense that, say, Java does. If your code is throwing exceptions, pull up a console and use the debugger to fix them. JS exceptions are slow, and really not meant to be used for flow control. A method won't throw an exception unless there's a serious problem — and it's usually a programming error.
Here's an alternative answer than the window.onerror solution. This isn't something I've used in production, but is something that I just like because of the flexibility (i.e. you could use it to debug things like timing how long a method took or something).
Whilst you could probably pass window into it (don't quote me on that, and don't think it's a good idea) it does work if you have all your methods in an object:
(function(obj) {
for (var name in obj) {
if (typeof(obj[name]) == 'function') {
currentMethod = obj[name];
obj[name] = function() {
try {
currentMethod();
}
catch (e) {
alert('Exception Handler: ' + e);
}
};
}
}
}(myObject));
Here's it working: http://jsfiddle.net/jonathon/kpYnW/
Basically, it goes through each property in your object, finds the ones that are functions and wraps them in a try/catch (or whatever else you want).
Whether or not it's efficient is a different matter - I've just found it a very useful technique for debugging. Unfortunately I can't remember the original place I read it but if anyone knows, please add as a comment.

Categories

Resources