Deep Tech Point
first stop in your tech adventure

What is a catch clause in JavaScript?

November 3, 2021 | Javascript

This article will take you into the world of JavaScript errors. Errors happen no matter what, no matter how extraordinary a coder you are, no matter how closely you pay attention, no matter how good you are at predicting a user’s behavior. In JavaScript, your scripts will have errors. And there are a hundred possible reasons for that. However, there is a solution to discovering these errors, and that solution comes in a form of a catch clause through a try statement.

What is a catch clause in a try statement in JavaScript?

Although the title of this article strictly focuses on a catch statement, the keyword comes in a pair with the try statement. These two keywords are inseparable and form a try catch syntax construct which at the end of the day enables us to catch the errors that mess with our code. As a matter of fact, the try statement helps us define a part of the code we need to test for errors while the code is being carried out, and the catch statement helps us pinpoint a block of the code that needs to be carried out if an error occurs in the try block.

The syntax of the try catch statement has two main blocks, first the try{}, and then catch{} block, and it looks like this:

try {
  a block of code the engine needs to try
}
catch(error) {
  a block of code that handles errors
}

So, how does the catch clause in the try statement work? First, the engine carries out the code in the try{} block. If the engine cannot find any errors in the try{} block, it simply goes through the entire try{} block and ignores the catch{} block. However, if an engine finds an error in the try{} block, the engine stops carrying out the rest of the try{} block, but it does not kill the script as it would otherwise, instead it jumps to the beginning of the catch(error){} block and enables us to handle the error in a catch(error){} part of the statement.

We can use any name for the variable, in our example, we used the error name for the variable. The point is that the variable will contain an error object and all the details about the error.

Adding finally clause to the try statement with a catch clause

The syntax of the try catch finally statement has three main blocks, first the try{}, and then catch{} block, and then the finally{} block:

try {
  a block of code engine needs to try
}
catch (error) {
  a block of code that needs to handle errors
}
finally {
  a block of code that is carried out regardless of whether an exception was thrown or caught
}

Let’s quickly glance through the syntax. Similar to the syntax in the try statement with a catch clause – if the engine cannot find an error in the try block, the catch block is skipped. If it finds an error, the control is promptly relocated to the catch-block, where we define what should be done if an error in the try block occurs.
But, what about the finally block? The finally part of the statement is always carried out after the try and catch block are done executing, whether an error in the try block was caught or not and the catch block was executed or not. Here we have an example where we used the finally block, which will always be carried out:

<script>
    function greeting(){
        document.writeln("greeting() : Hello!");
    }
    function goodbye(){
        document.writeln("goodbye() : Bye bye!");
    }
    
    try{
        greeting()
        asking()
    } catch(err){
        document.writeln("asking() : " + err);
    } finally{
        goodbye()
    }
</script>

The result from the example above is:

welcome() : Hello!
asking() : ReferenceError: asking is not defined
bye() : Bye bye!

What you should take from this paragraph about the finally clause? The finally clause will be carried out regardless of whether or not an exception is thrown. Nevertheless, if you throw an exception, the statements in the finally clause execute even if no catch clause handles the exception.

The example below shows how you can use the finally clause when an exception occurs, so your script will at least fail gracefully. For example, your script has tied up a resource and you may need to release that resource. In the example below we will open a file and then execute the statements that allow us to access that file. While that file is open, if, for any reason, an exception is thrown, the finally clause will close the file before the script fails.


openFile()
try {
   // script has tied up a resource and you we need to release that resource
   writeFile(myData);
}
finally {
   closeFile(); // it will always close the resource, even if an exception is thrown, the finally clause will close the file before the script fails
}

What about unconditional and conditional catch-block

Since this article is about a catch clause, we should pay a bit more attention to the catch-block, in terms of unconditional vs. conditional catch block.
The theory is pretty simple when we use a single, unconditional catch clause – the catch block is entered when any exception is thrown. In the following example, when the exception occurs, the control is transferred to the catch clause.

try {
   throw "someException"; // this will create an exception
}
catch (exc) {
   // here we have statements that handle any exceptions
   logErrors(exc); // this helps us pass an exception object to the error handler
}

What about conditional catch-blocks? First, let’s bring out that this functionality is not a standard and is not a part of the ECMAScript specification. For that reason, you shouldn’t use this feature on production sites that are web-oriented, because it will not work for every user. However, there are situations when one or more conditional catch-blocks make sense because they need to handle particular exceptions. In cases like this, a specific catch clause is in control when a specific exception is thrown.
If we take a look at the example below, a code in the try block can throw three exceptions: TypeError, RangeError, and EvalError. So, when one of these errors occurs, the control is transferred to the catch clause that is tied to the specific error. On the other hand, if the error or exception is not listed as one of the specified exceptions and if there is an unconditional catch clause found, the control is shifted to that unconditional catch clause. It is also worth mentioning, that if you use a conditional catch clause(s) in combination with the unconditional catch clause, you must specify the unconditional catch clause as the last one on the list. If you don’t specify the unconditional catch clause at the end, it could interrupt all types of exceptions that are “reserved” for a conditional catch clause.

try {
    myCode(); // a code in the try block can throw three types of exceptions: TypeError, RangeError, EvalError
} catch (exc) {
    if (exc instanceof TypeError) {
        // a statement that handles TypeError exceptions
    } else if (exc instanceof RangeError) {
        // a statement that handles RangeError exceptions
    } else if (exc instanceof EvalError) {
        // a statement that handles EvalError exceptions
    } else {
       // a statement that handles any unspecified exceptions
       logMyError(exc); // pass exception object to error handler
    }
}

Can I nest more than one try statement?

Yes, you can. And the inner try statements can, but don’t have to, contain their own catch block. If you omit the inner catch block for the inner try statement, the engine will use the catch block that is enclosing the outer try statement. In general, there are more practical and neater ways to avoid nesting try statements, especially since JavaScript has a finally construct, which might in some cases help. Before you nest the try statement, you might consider the following approaches. For example, consider refactoring the inner try and catch blocks into separate functions, and try to be more particular about specific exceptions that are caught – do you really want to handle all of the exception subclasses to be handled the same way. As said earlier, the finally block might often make a lot of sense.

Below you’ll find a simple example of a nested try statement:

try {
  try {
    throw new Exemption("pardon");
  }
  finally {
    console.log("finally");
  }
}
catch (e) {
  console.error("outer", ex.message);
}

And the output is:

// "finally"
// "outer" "pardon"