Last week, we looked at throwing errors in JavaScript using the throw statement. Today, let's look at how we can catch errors using the try...catch block.

Here's our complete sum() function from last week:

function sum(num1, num2) {
const type1 = typeof num1, type2 = typeof num2;

if (type1 !== 'number' || type2 !== 'number') {
throw new TypeError(`Expected two numbers; got ${type1} and ${type2}.`);
}

return num1 + num2;
}

The function adds two numbers together and returns the result. If either of its arguments isn't a number, it throws a TypeError. This is something we can catch using a try...catch block.

Before we get started, notice that if we don't explicitly catch the error, the console specifies that it's uncaught:

Uncaught TypeError: Expected two numbers; got number and string.
sum file:///Users/kieranbarker/Desktop/tmp.js:5
<anonymous> file:///Users/kieranbarker/Desktop/tmp.js:11

The try...catch block

Let's see how we can catch that error using a try...catch block:

try {
sum(1, '2');
} catch (error) {
console.error(error);
}

We put the code we want to try inside the try block. We then have access to the error inside the catch block, where we can catch it. In this example, all we do is log the error to the console, so this doesn't provide much benefit. But note that the TypeError is no longer labelled as uncaught, because we've explicitly caught it:

TypeError: Expected two numbers; got number and string.
sum file:///Users/kieranbarker/Desktop/tmp.html:15
<anonymous> file:///Users/kieranbarker/Desktop/tmp.html:24

If you don't need to actually use the error within the catch block, you don't have to specify it. In the following example, we just log a friendly warning to the console, rather than a scary stack trace:

try {
sum(1, '2');
} catch {
console.warn('Whoops, something went wrong!');
}

The finally block

You can also add a finally block to the end, which contains code that will always run after the try...catch block, regardless of whether it was the try block or the catch block that ran:

try {
sum(1, '2');
} catch {
console.warn('Whoops, something went wrong!');
} finally {
console.log('This will always run.');
}

I've never seen the point of it, though. Why not just place the code after the try...catch block, omitting the finally block entirely?

try {
sum(1, '2');
} catch {
console.warn('Whoops, something went wrong!');
}

console.log('This will always run.');

One of the tenets of The Zen of Python is actually that flat is better than nested. I know we're talking about JavaScript—not Python—but I have to agree. Why nest the code when you don't need to? It only hinders readability.

It's like the do...while loop. Have you ever found a use for that? Nope, me neither.