Get the actual Javascript Error object with window.onerror - javascript

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);
});

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.

How to create, design and throw built-in Error objects

UPDATE
[Rewriting question to focus on the problem I am trying to understand.]
Is there a means in JavaScript to throw Exceptions that notify the line number where the problem occurs? Similar to C#'s debugger, if an error is thrown on line 50 then I will be taken to line 50.
For example, according to MDN EvalError represents an error with eval(). So, let's say I have a function that uses eval(). I want to use a specific error that is representative of the problem at hand, EvalError:
//As written here the error implies there is a problem on this line. See Firebug console window
var evalErra = new EvalError('required element missing from evaluation');
var stringFunc = "a=2;y=3;document.write(x*y);";
EvalString(stringFunc);
function EvalString(stringObject) {
//Some arbitrary check, for arguments sake let's say checking for 'x' makes this eval() valid.
if(stringObject.indexOf('x') !== -1) {
throw evalErra;
//throw 'required element missing from evaluation';//This way offers no line number
}
eval(stringFunc);//The problem really lies in the context of this function.
}
If I'm going about this all wrong, then please tell me how I should approach these kinds of issues.
When you throw an error, execution of the current code will stop and JS will work its way back up the execution tree until it finds a catch () which handles the particular type of error being thrown, or gets all the way up to the top of the tree, causing an "unhandled exception" error: You threw an error, and nothing caught it, and now someone's window got broken.
try {
if (true) {
throw 'yup'
}
} catch (e) { // catches all errors
... handle the error
}
When doing error handling you want to do the following
throw new Error("message");
Then if you ever handle this error look at err.stack (firefox/opera/chrome) or err.line (Safari) or err.IE_Y_U_NO_SHOW_ME_ERROR_LINE_NUMBER (IE) to find the line number.
If you want you can subclass Error.

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.

onerror handling with VS2008

function testFun() {
onerror = function() { log("caught the error"); return true; };
setTimeout(function() { throw "bad bad bad"; }, 300);
};
This is sample, code, but it demonstrates a problem.
If I run this in FF, or IE7, it prints the sensible "caught the error" message (assume a reasonable 'log' function).
However if I debug the code in VS2008, the debugger stops on the throw with the message: 'Microsoft JScript runtime error: Exception thrown and not caught'. If I say 'continue' or 'ignore', the log message is not produced.
This is a problem since the real code I am working with is much larger than this, and I'll occasionally want to, you know, debug stuff. So two questions:
Any know why and can I modify this behaviour with some flag I don't know about?
Am I doing what I think I'm doing (setting the global 'onerror' handler) in this code? If not, what is the appropriate pattern for catching this type of error?
Note: There is no difference wrt this problem if I use window.onerror instead.
According to this defining a global onerror function doesn't work in IE. They were probably talking about IE6 or earlier, so maybe MS have fixed it for IE7 - however I wouldn't expect this to just automatically flow through to the VS debugger.
At any rate, try using window.onerror = function rather than just onerror.
If that doesn't work, you'll have to use a try/catch block inside your timer function I guess.
PS: Get firefox and use firebug. the debugger (and everything else) is much better and nicer to use than the VS debugging

JavaScript Exception Handling

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

Categories

Resources