blog/engineering/javascript/JavaScript try catch: all you need to know

JavaScript try catch: all you need to know

4 undefinedpublished 15 February 2022updated 26 January 2023

EPAM Anywhere’s Chief Software Engineer I, Rufat Khaslarov, guides you through JavaScript try catch in this brief coding lesson with examples.

Have you ever made a mistake in your code that could not be executed afterward? Or have you sent a request to a server that failed and led to some unexpected consequences? Of course you have — like so many of us.

Such errors have mysterious names and are called exceptions. You might wonder how best to deal with them. Every programming language gives us some tools for that, and JavaScript is no exception.

To address these errors in JavaScript, we’re going to learn and use the try/catch construction. Let’s roll!

Handling errors with JavaScript try catch

In general, try/catch in JavaScript looks like this:

The try block contains a set of statements where an exception can occur, and is always followed by a catch block, which handles the exception that occurs in the associated try block. The catch block “catches” an error so that you can get more information about it by checking the properties of the error object.

In addition to the try/catch construction, the “throw” keyword is also widely used in this context. By applying it, we can create our own customized errors. This makes our application and business logic more powerful, understandable, and, I’d say, human-readable.

The first real-world example off the top of my head is data validation:

In the code snippet, we’re trying to retrieve the token from the query property of the request. If there’s no token, or the value is empty, we’re literally “throwing” an error, which is caught by the catch block and shown in the logs. Our exploration doesn’t stop here.

Since Error is a class, it's obviously possible to create our own error classes for the sake of clarity. Check it out:

In this example, we’ve created our own ValidationError class and used it for error handling of the specific business logic above. In the logs, it comes up as “Failed to authenticate ValidationError. Have not received [token]”. Applying this technique, you can determine the error type and handle it differently:

Rethrowing an error

The last technique I’ll mention here is to rethrow an error. Use it when you need to handle an error on the upper stage, not inside a particular handler.

There’s a de facto standard according to which the error handler (or a particular catch block) should handle the error specifically related to it, while everything else should be rethrown further. In the end, there should be a default error handler that handles everything that was not caught by our gatekeepers (catch blocks):

Now, let’s refactor our code a bit. It’s better to move the validation code to a separate function for readability purposes:

Using the finally block

Sometimes, it might be required in cases of try/catch and success/fail that there be some finalizing and independent action. The basic use case is as follows: a code opens a file descriptor; reads/processes data inside it; and, in case of an error or a successful completion, the file should be closed and resources released.

For this purpose, you can use the try/catch/finally construction in JavaScript:

Note that all the aforementioned code is synchronous. In the modern JavaScript (ES2017 and later) try/catch/finally can be fully used with async functions. For more detail, please see this tutorial.

Let’s assume that the authenticate function is async:

So, if the promise is rejected, the catch block will handle it in the same way as above.

In conclusion: avoid nested try/catch

One more piece of advice: try to avoid nested try/catch blocks. If you include them, your code probably violates the SRP. As a quick fix, you might try to move one of the blocks to a separate function.

get the latest tech insights, career growth, and lifestyle tips right in your inbox