Javascript Global Error Catching
Contents |
Web Dev @ Microsoft SEO By WooRank Books Courses Screencasts Newsletters Versioning Shop Forums Advertise Contribute Contact Us Our Story 995kSubscribers 132kFollowers javascript window.onerror stack trace 80kFollowers JavaScript Article A Guide to Proper Error Handling in JavaScript By Camilo window addeventlistener error Reyes April 13, 2016 This article was peer reviewed by Tim Severien and Moritz Kröger. Thanks to all of SitePoint's
Catch All Javascript Errors
peer reviewers for making SitePoint content the best it can be! Ah, the perils of error handling in JavaScript. If you believe Murphyʼs law, anything that can go wrong, will go wrong!
Javascript Onerror Image
In this article I would like to explore error handling in JavaScript. I will cover pitfalls and good practices. We'll finish by looking at asynchronous code and Ajax. More from this author Saved from Callback HellQuick Tip: How to Throttle Scroll EventsGetting Started with the Raspberry Pi GPIO Pins in Node.js I feel JavaScriptʼs event-driven paradigm adds richness to the language. I like to imagine the window.onerror not working browser as this event-driven machine, and errors are no different. When an error occurs, an event gets thrown at some point. In theory, one could argue errors are simple events in JavaScript. If this sounds foreign to you, buckle up as you are in for quite a ride. For this article, I will focus only on client-side JavaScript. This write up will build on concepts explained in the article Exceptional Exception Handling in JavaScript. To paraphrase: “with an exception JavaScript checks for exception handling up the call stack.” I recommend reading up on the basics if you are not familiar. My goal is to explore beyond the bare necessities for handling exceptions. The next time you see a nice try...catch block, it will make you think twice. The Demo The demo we'll be using for this article is available on GitHub, and presents a page like this: All buttons detonate a “bomb” when clicked. This bomb simulates an exception that gets thrown as a TypeError. Below is the definition of such a module with unit test. function error() { var foo = {}; return foo.bar(); } To begin, this function declares an empty empty object name
a fair amount of JavaScript and that is viewed in lots of different browsers (mobile, tablet, desktop). Naturally we want to log our JavaScript exceptions and their stacktraces, just
Exception Handling In Javascript Example
like we log server-side exceptions. It is impossible to test every combination javascript error handling best practices of device and browser so we rely on logging to find the edge cases we miss in our testing. window.onerror script error The way we handle our JavaScript exceptions is to: catch the exception. collect data about the useragent, context etc. Save it to our logs by sending an ajax request with https://www.sitepoint.com/proper-error-handling-javascript/ the data and the exception information. I can finally log JS Exceptions! We decided to use window.onerror which is a DOM event handler that acts like a global try..catch. This is great for catching unexpected exceptions i.e. the ones that never occur while testing. It is very simple to get started with, you just have to override the handler like this: window.onerror https://danlimerick.wordpress.com/2014/01/18/how-to-catch-javascript-errors-with-window-onerror-even-on-chrome-and-firefox/ = function (errorMsg, url, lineNumber) { alert('Error: ' + errorMsg + ' Script: ' + url + ' Line: ' + lineNumber); } But It Was Too Good To Be True If you test this on a local server (say IIS or nginx) then it should work fine. But it is not the same as a normal try..catch, so producing a stacktrace with a library like stacktrace.js will probably not work too well. The window.onerror handler does not have the same context and the context varies enormously from browser to browser. Also, if you have minified your files then line number is not very useful. For example: Error: ‘a’ is undefined Script: build.js Line: 3 Variable ‘a' is very hard to find when line 3 has 30000 characters of minified JavaScript. Unfortunately, I do not have a solution for this for all browsers. This will get better over the next few months as a new standard for window.onerror has been agreed upon. It is already implemented for Chrome. The new standard adds two parameters; column number and an error object. Our window.onerror handler now l
as expected is a good start. Making your programs behave properly when encountering unexpected conditions is where it really gets challenging. ¶ The problematic situations that a program can encounter fall into two categories: Programmer http://eloquentjavascript.net/1st_edition/chapter5.html mistakes and genuine problems. If someone forgets to pass a required argument to a https://blog.sentry.io/2016/01/04/client-javascript-reporting-window-onerror.html function, that is an example of the first kind of problem. On the other hand, if a program asks the user to enter a name and it gets back an empty string, that is something the programmer can not prevent. ¶ In general, one deals with programmer errors by finding and fixing them, and with genuine errors by having script error the code check for them and perform some suitable action to remedy them (for example, asking for the name again), or at least fail in a well-defined and clean way. ¶ It is important to decide into which of these categories a certain problem falls. For example, consider our old power function:function power(base, exponent) { var result = 1; for (var count = 0; count < exponent; count++) result *= base; return result; javascript global error } ¶ When some geek tries to call power("Rabbit", 4), that is quite obviously a programmer error, but how about power(9, 0.5)? The function can not handle fractional exponents, but, mathematically speaking, raising a number to the halfth power is perfectly reasonable (Math.pow can handle it). In situations where it is not entirely clear what kind of input a function accepts, it is often a good idea to explicitly state the kind of arguments that are acceptable in a comment. ¶ If a function encounters a problem that it can not solve itself, what should it do? In chapter 4 we wrote the function between:function between(string, start, end) { var startAt = string.indexOf(start) + start.length; var endAt = string.indexOf(end, startAt); return string.slice(startAt, endAt); } ¶ If the given start and end do not occur in the string, indexOf will return -1 and this version of between will return a lot of nonsense: between("Your mother!", "{-", "-}") returns "our mother". ¶ When the program is running, and the function is called like that, the code that called it will get a string value, as it expected, and happily continue doing something with it. But the value is wrong, so whatever it ends up doing with it will also be wrong. And if you are unlucky, this wrongness on
to log client-side errors and report them to your servers. It’s also one of the major mechanisms by which Sentry’s client JavaScript integration (raven-js) works. You listen to the onerror event by assigning a function to window.onerror: window.onerror = function (msg, url, lineNo, columnNo, error) { // ... handle error ... return false; } When an error is thrown, the following arguments are passed to the function: msg – The message associated with the error, e.g. “Uncaught ReferenceError: foo is not defined” url – The URL of the script or document associated with the error, e.g. “/dist/app.js” lineNo – The line number (if available) columnNo – The column number (if available) error – The Error object associated with this error (if available) The first four arguments tell you in which script, line, and column the error occurred. The final argument, Error object, is perhaps the most valuable. Let’s learn why. The Error object and error.stack At first glance the Error object isn’t very special. It contains 3 standardized properties: message, fileName, and lineNumber. Redundant values that already provided to you via window.onerror. The valuable part is a non-standard property: Error.prototype.stack. This stack property tells you at what source location each frame of the program was when the error occurred. The stack trace can be a critical part of debugging an error. And despite being non-standard, this property is available in every modern brow