Handling and Reporting Errors in JavaScript
Proper methods and techniques for handling and reporting errors are fundamental to any programming language. However, it is also one of those programming practices that is largely overlooked. JavaScript is no different in that aspect. More often than not, in JavaScript, developers end up writing code that works without giving much thought about the cases where the code might fail or how to handle the errors. Interestingly, when an error occurs, JavaScript will fail silently without giving you much clue about what went wrong.
To understand the basics of JavaScript error reporting, we need to have a better look at how the interpreter works under the hood. This article covers that and more. You will learn about different classes of errors in JavaScript, the techniques that you can use to handle them and some tools for monitoring errors. Let’s get started.
The Theory
If you’re curious about what happens under the hood, it’s not as easy as it appears to the end user. When an error is encountered, the interpreter stops execution and an exception is thrown. The interpreter looks for an exception handling mechanism and when it doesn’t find one, it jumps out of the current function. But things don’t stop there. The program returns from all the functions in the call stack until it either reaches the top level function that started the execution (thus terminating the program) or an exception handler is found.
If the program always returned to the top-level exception handlers when an error is encountered, the user experience will be downright disastrous. Instead, we need a more novel method to handle the exception, report the error gracefully and then continue with the program execution from that point where the error was caught.
In this article, I am going to discuss different errors you might encounter in JavaScript, the best practices to encounter such errors and the different tools that might help you in reporting JavaScript errors and exceptions.
Common Errors and Exceptions
Here are the common errors in JavaScript that you may come across.
Generic Error
A generic Error usually represents a user-defined error. You can use the Error type to create Error objects that are specific to your use case. For instance, here is an Error object being instantiated.
var error = new Error("An error has been encountered");
Syntax Errors
Syntax errors are the errors that are impossible to avoid. They are the errors that occur when you try to do something that breaks the grammar rules of language. Also known as parsing errors, they can be identified only during execution in JavaScript because JavaScript is an interpreted language. Missing brackets, parentheses etc. are some of the common syntax errors.
const a = (state => {
console.log(3)
}
Type Error
You run into this error when the value passed to a function as either operand or argument doesn’t match with the expected type. Here is an example:
const a = null;
console.log(a.name);
//Uncaught TypeError: Cannot read property 'name' of null
Reference Error
A reference is encountered when a non-existent variable or a variable that hasn’t been declared yet is being referenced. This usually happens when you misspell a variable name or the variable is used beyond its original scope. The example below demonstrates a few common occurrences of the reference error.
const bob = “Bob”;
state = Bob;
//Uncaught ReferenceError: Bob is not defined
{
let a = "This has limited scopes"
}
console.log(a);
//Uncaught ReferenceError: Bob is not defined
Range Error
Range error occurs when a value isn’t in the range or the sets of allowed values. This usually happens when you try to pass a number as an argument to a function and the number doesn’t fall into the argument’s range.
var pi = 3.14159;
pi.toFixed(100000);
//RangeError: toFixed() digits argument must be between 0 and 100
There are two more types of error objects; URI Error and Eval Error. You can read more about the types of errors in JavaScript in the official MDN page.
Handling Exceptions in JavaScript
In JavaScript, you have many ways that you could check for exceptions and handle them; but some of the techniques are best avoided. I’ve listed a couple of ways that I think are best while handling errors in JavaScript.
The try… catch statement
This is one of the popular ways for catching errors in JavaScript and many other programming languages have implemented this practice for error reporting.
The try block contains a set of statements where an exception might occur. The try block is usually followed by a catch block or a finally block or both. The statements are tested for errors inside try and if an exception is found, it looks to handle those exceptions using a catch block first.
try {
// tries to execute this block
} catch (exception) {
// this code handles exceptions
} finally {
// this code always gets executed
}
When an exception occurs, the catch clause is executed and its argument receives the exception. You can then display an error or handle the exception in a novel way without degrading the user experience.
The finally block is executed regardless of whether an exception occurs or not. However it’s completely optional. Checkout the example below that demonstrates try...catch in action:
try {
eval('alert("Hello world)');
}
catch(error) {
console.log(error);
// expected output: SyntaxError: unterminated string literal
// Note - error messages will vary depending on browser
}
finally {
console.log("Inside finally block");
}
Throwing Exceptions
The throw statement lets you intentionally throw user-defined exceptions. When the interpreter runs into a throw statement, it stops the execution process and then looks for a catch clause in the call stack. If it doesn’t find one, the program is terminated.
Throwing exceptions is particularly helpful when you’re debugging your code. You can use this technique to isolate the errors and/or find out what went wrong. Here is an example:
if (denominator === 0)
throw new Error("Division By zero error!");
Reporting and Monitoring JavaScript Errors
As a developer, you always would want to capture all the bugs in the development phase itself. But that’s not what happens in real life. Even if there are unit tests and other barriers in place; errors will creep into your production build. Therefore, it’s essential that you have definite plan for monitoring reporting JavaScript errors and take necessary actions when that happens. The best possible solution will be to build a custom script using some of the open-source tools available because that gives you the flexibility to have full control over the JavaScript error reporting mechanism.
You can log the exception events to console and to a database and trigger the mailer to send you a mail when something goes wrong. Otherwise, there are error tracking solutions, both free and paid, that let you monitor everything that needs to be monitored and create health reports about your JavaScript application. Most of the popular JavaScript error reporting tools online have all the essential features from tracking different errors, categorizing them, monitoring the health status and communicating the status back to you.
Summary
Handling errors and exceptions the right way is something that you should spend your money and time on. Experiencing errors in production degrades the experience of the user and can negatively impact your business. So, it’s essential that you have good roadblocks for catching the errors, monitoring them and if essential, a mechanism to report critical JavaScript errors back to the user.
Another choice for debugging in javascript
Great article. To add, a nifty way I found to log/output the errors is using the window.onerror , this way you can just have you ‘throw new error(‘error’)’ and you can have a function attached to the window: window.onerror = e => console.log(e)