JavaScript Try-Catch Error and Exception Handling Guide

Maxwell
Level Up Coding
Published in
8 min readOct 17, 2022

--

In any software development project, handling errors and exceptions is critical to the success of the application. Whether you’re a novice or an expert, your code can fail for a variety of reasons, such as a simple typo or unexpected behavior from an external service.

Because there is always a chance that your code will fail, you need to prepare for this situation by making your code more robust. You can do this in a number of ways, but a common solution is to make use of the try-catch statement. This statement allows you to wrap a block of code to try and execute. If any errors occur during execution, this statement will "catch" them and you can quickly fix them before your application crashes.

This article will serve as a practical introduction to try-catch statements and show you how to use them to handle errors in JavaScript.

1. Why Try-Catch Is Needed

Syntax errors occur when you don’t follow the rules of a particular programming language. These errors can be detected by configuring a linter, a tool used to analyze code and flag stylistic or programming errors. For example, you can use ESLint to find and fix bugs in your code question.

Here is an example of a syntax error:

console.log(;)

In this case, the error occurs because the syntax of the code is incorrect. It should be as follows:

console.log('Maxwell');

Runtime errors occur when an application has problems running. For example, your code might try to call a method that doesn’t exist. To catch these errors and apply some processing, you can use the try-catch statement.

2. What Is an Exception

An exception is an object that indicates that a problem has occurred during program execution. These problems can occur when accessing invalid array indices, when trying to access some member of a null reference, when trying to call a function that does not exist.

For example, nsider a scenario where an application relies on a third-party API. Your code may process responses from this API expecting them to contain certain properties. If this API returns an unexpected response for any reason, it may trigger a runtime error. In this case, instead of allowing the error to crash the application, you can wrap the affected logic in a try-catch statement and provide an error message to the user or even call some fallback logic.

3. How Try-Catch Works

Simply put, a try-catch statement consists of two blocks of code—one prefixed with the try keyword and the other with the catch keyword—and a block in which the error object is stored variable name. If the code inside the try block throws an error, the error will be passed to the catch block for processing. If it doesn't throw an error, the catch block will never be called. Consider the following example:

In this example, when the function is called, the runtime will see that there is no such function and throw an error. Thanks to the try-catch statement surrounding it, this error is not fatal and can be handled however you like. In this case, it is passed to console.log, which tells you what the error was.

There is another optional statement called the finally statement, which, when present, is always executed after try and catch, regardless of whether catch is executed. It is typically used to include commands that free resources allocated during a try statement that may not have had a chance to clean up gracefully in the event of an error. Consider the following example:

In this contrived example, assume a file is opened before the try-catch-finally statement. If an error occurs during a try block, be sure to close the file to avoid memory leaks or deadlocks. In this example, the finally statement ensures that no matter how the try-catch executes, the file will be closed before continuing.

Of course, wrapping potentially error-prone code with try-catch statements is only part of the fault-tolerance puzzle. The other part is knowing what to do when an error is thrown.

Sometimes it may make sense to display them to the user (usually in a more readable format), and sometimes you may want to simply record them for future reference. Either way, it helps to be familiar with the Error object itself so you know what data you have to deal with.

4. Error Object

Whenever an exception is thrown in a try statement, JavaScript creates an Error object and sends it as an argument to the catch statement. Typically, this object has two main instance properties:

  • name:a string describing the type of error
  • message:more detailed error description

As mentioned earlier, the value of the name attribute refers to the type of error that occurred. Here is a non-exhaustive list of some of the more common error types:

  • ReferenceError:throws ReferenceError when a reference to a non-existing or invalid variable or function is detected.
  • TypeError:a TypeError will be thrown when a value is used in a way that is incompatible with its type, such as attempting to call a numeric string function ((1).split(',');).
  • SyntaxErrorSyntaxError is thrown when there is a syntax error while interpreting the code; for example, when parsing JSON with a trailing comma (JSON.parse('[1,2,3,4,]');).
  • SyntaxErrorURIError is thrown when an error occurs in URI processing; for example, an invalid parameter is passed in decodeURI() or encodeURI().
  • RangeErrorRangeError is thrown when a value is not in the set or range of allowed values; for example, a string value in a numeric array.

All native JavaScript errors are extensions of the generic Error object. Following this principle, you can also create your own error types.

5. Custom Errors

Another keyword in JavaScript that is closely related to errors and error handling is throw. When using this keyword, user-defined exceptions can be "thrown". When you do this, execution of the current function will stop and any value used with the throw keyword will be passed to the first catch statement in the call stack. Without a catch statement to handle it, the behavior will be similar to a typical unhandled error and the program will terminate.

Throwing custom errors is useful in more complex applications because it gives you another way to flow control your code. Consider a scenario where you need to validate some user input. If the input is considered invalid according to business rules, you do not want to continue processing the request. This is a perfect use case for the throw statement. Consider the following example:

A custom error class is defined here that can extend the generic error class. This technique can be used to throw errors specifically related to business logic, not just the default errors used by JavaScript engines.

6. When To Use Try-Catch

Because errors climb up the call stack until they find a try-catch statement or the application terminates, it is easy to simply wrap the entire application in one large try-catch statement or many smaller try-catch statement, so you can enjoy the fact that the application will not technically crash again. However this is not a good idea.

When it comes to programming, bugs are a fact and they play an important role in the life cycle of an application. They will tell you what went wrong. Therefore, if you want to provide a good experience for your users, you must use the try-catch statement respectfully and carefully.

try-catch statements should generally be used where errors are reasonably expected to occur. However, once you catch an error, you usually don't want to delete it outright. As mentioned earlier, when an error is thrown, it means that an error has occurred. You should use this opportunity to handle errors appropriately, either by displaying better error messages to the user in the UI, or sending errors to application monitoring tools (if any) for aggregation and later analysis.

In general, when wrapping code in a try-catch statement, you should only wrap code that is conceptually related to the expected error. If the size of the function is fairly small, this may mean wrapping the entire function body. Alternatively, you might have a larger function where all the code in the body is wrapped, but spread across multiple try-catch statements. This can actually serve as an indication that the feature in question is too complex and or handles too much responsibility. Such code can be broken down into smaller, more focused functions.

For areas of the code where errors are less likely to occur, it is often best to forego excessive try-catch statements and simply allow errors to occur. It may sound counterintuitive, but allowing your code to fail fast is actually putting yourself in a better position. Compression errors may give a stable appearance, but there are still potential problems.

Allowing bugs to occur without explicit handling means that when interacting with application monitoring tools such as BugSnag or Sentry, you can globally intercept and log errors for later analysis. These tools allow you to see where bugs actually are in your application so you can fix them instead of blindly ignoring them.

7. Async Function

To understand what an asynchronous function in JavaScript is, you must understand Promise

A promise is essentially an object that represents the eventual completion of an asynchronous operation. They define actions to be performed in the future, which will eventually resolve (success) or reject (error).

For example, the following code shows a simple Promise that resolves a value quickly. Then pass that value to the then callback function:

The next example shows how an error thrown in a Promise will be handled by a Promise catch callback:

Instead of manually throwing an error in a promise, you can use the reject function. This function is provided as the second parameter of the callback function of the Promise:

You might notice something odd in the last example. There is a difference between throwing an error and reject. Throwing an error will stop the execution of the code and pass the error to the most recent catch statement or terminate the program. reject A Promise will call the catch callback function, but it will not stop the execution of the Promise if there is more code to run, unless the call to the reject function is prefixed with the return keyword . That's why the console.log(a + b); statement is still fired even after reject. To avoid this behavior, simply use return reject(…) to end execution early.

8. Summarize

The try-catch statement is a useful tool that will definitely be used in a programmer's career. However, any method used indiscriminately may not be the best solution. Remember, you need to use the right tools and concepts to solve specific problems. For example, a try-catch statement is usually not used when you don't want any exceptions to occur. If errors do occur in these situations, you can identify and fix them as they occur.

--

--

A front-end enthusiast, a development engineer willing to learn more about development techniques and collaborate to build better software.