Handling Exceptions in JavaScript
Tags: javascript, webdev, tutorial, beginners
Published: 2020-01-09 03:14:55

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

**Follow me on Twitter at https://twitter.com/AuMayeung**

**Many more articles at https://medium.com/@hohanga**

Like any programs, JavaScript will encounter error situations, for example, like when JSON fails to parse, or null value is encounter unexpectedly in a variable. This means that we have to handle those errors gracefully if we want our app to give users a good user experience. This means that we have to handle those errors gracefully. Errors often come in the form of exceptions, so we have to handle those gracefully. To handle them, we have to use the `try...catch` statement to handle these errors so they do not crash the program.

Try…Catch
=========

To use the `try...catch` block, we have to use the following syntax:

```javascript
try{  
  // code that we run that may raise exceptions  
  // one or more lines is required in this block  
}  
catch (error){  
  // handle error here  
  // optional if finally block is present  
}  
finally {  
  // optional code that run either   
  // when try or catch block is finished  
}
```

For example, we can write the following code to catch exceptions:

```javascript
try {  
  undefined.prop  
} catch (error) {  
  console.log(error);  
}
```

In the code above, we were trying to get a property from `undefined`, which is obviously not allowed, so an exception is thrown. In the `catch` block, we catch the ‘TypeError: Cannot read property ‘prop’ of undefined’ that’s caused by running `undefined.prop` and log the output of the exception. So we get the error message outputted instead of crashing the program.

The `try...catch` statement has a `try` block. The `try` block must have at least one statement inside and curly braces must always be used, event for single statements. Then either the `catch` clause or `finally` clause can be included. This means that we can have:

```javascript
try {  
  ...  
}   
catch {  
  ...  
}

try {  
  ...  
}   
finally{  
  ...  
}

try {  
  ...  
}   
catch {  
  ...  
}  
finally {  
  ...  
}
```

The `catch` clause has the code that specifies what to do when an exception is thrown in the `try` block. If they `try` block didn’t succeed and an exception is thrown, then the code in the `catch` block will be ran. If all the code in the `try` block is ran without any exception thrown, then the code in the `catch` block is skipped.

The `finally` block executes after all the code the `try` block or the `catch` block finishes running. It always runs regardless if exceptions are thrown or not.

`try` blocks can be nested within each other. If the inner `try` block didn’t catch the exception and the outer one has a `catch` block, then the outer one will catch the exception thrown in the inner `try` block. For example, if we have:

```javascript
try {  
  try {  
    undefined.prop
  finally {  
    console.log('Inner finally block runs');  
  }  
} catch (error) {  
  console.log('Outer catch block caught:', error);  
}
```

If we run the code above, we should see ‘Inner finally block runs’ and ‘Outer catch block caught: TypeError: Cannot read property ‘prop’ of undefined’ logged, which is what we expect since the inner `try` block didn’t catch the exception with a `catch` block so the outer `catch` block did. As we can see the inner finally block ran before the outer catch block. `try...catch...finally` runs sequentially, so the code that’s added earlier will run before the ones that are added later.

The `catch` block that we wrote so far are all unconditional. That means that they catch any exceptions that were thrown. The `error` object holds the data about the exception thrown. It only holds the data inside the `catch` block. If we want to keep the data outside it then we have to assign it to a variable outside the `catch` block. After the `catch` block finishes running, the `error` object is no longer available.

The `finally` clause contains statements that are excepted after the code in the `try` block or the `catch` block executes, but before the statements executed below the `try...catch...finally` block. It’s executed regardless whether an exception was thrown. If an exception is thrown, then statements in the `finally` block is executed even if no `catch` block catches and handles the exception.

Therefore, the `finally` block is handy for making our program fail gracefully when an error occurs. For example, we can put cleanup code that runs no matter is an exception is thrown or not, like for close file reading handles. The remaining code in a `try` block doesn’t executed when an exception is thrown when running a line in the `try` block, so if we were excepted to close file handles in the `try` and an exception is thrown before the line that closes the file handle is ran, then to end the program gracefully, we should do that in the `finally` block instead to make sure that file handles always get cleaned up. We can just put code that runs regardless of whether an exception is thrown like cleanup code in the `finally` block so that we don’t have to duplicate them in the `try` and `catch` blocks. For example, we can write:

```javascript
openFile();  
try {  
  // tie up a resource  
  writeFile(data);  
}  
finally {  
  closeFile();   
  // always close the resource  
}
```

In the code above, the `closeFile` function always run regardless of whether an exception is thrown when the `writeFile` is run, eliminating duplicate code.

We can have nested `try` blocks, like in the following code:

```javascript
try {  
  try {  
    throw new Error('error');  
  }  
  finally {  
    console.log('finally runs');  
  }  
}  
catch (ex) {  
  console.error('exception caught', ex.message);  
}
```

If we look at the console log, we should see that ‘finally runs’ comes before ‘exception caught error.’ This is because everything in the `try...catch` block is ran line by line even if it’s nested. If we have more nesting like in the following code:

```javascript
try {  
  try {  
    throw new Error('error');  
  }  
  finally {  
    console.log('first finally runs');  
  } 

  try {  
    throw new Error('error2');  
  }  
  finally {  
    console.log('second finally runs');  
  }  
}  
catch (ex) {  
  console.error('exception caught', ex.message);  
}
```

We see that we get the same console log output as before. This is because the first inner `try` block didn’t catch the exception, so the exception is propagated to and caught by the outer `catch` block. If we want to second `try` block to run, then we have to add a `catch` block to the first `try` block, like in the following example:

```javascript
try {  
  try {  
    throw new Error('error');  
  }  
  catch {  
    console.log('first catch block runs');  
  }    
  finally {  
    console.log('first finally runs');  
  } 

  try {  
    throw new Error('error2');  
  }  
  finally {  
    console.log('second finally runs');  
  }  
}  
catch (ex) {  
  console.error('exception caught', ex.message);  
}
```

Now we see the following message logged in order: ‘first catch block runs’, ‘first finally runs’, ‘second finally runs’, ‘exception caught error2’. This is because the first `try` block has a `catch` block, so the the exception caused by the `throw new Error('error')` line is now caught in the `catch` block of the first inner `try` block. Now the second inner `try` block don’t have an associated `catch` block, so `error2` will be caught by the outer `catch` block.

We can also rethrow errors that were caught in the `catch` block. For example, we can write the following code to do that:

```javascript
try {  
  try {  
    throw new Error('error');  
  } 
  catch (error) {  
    console.error('error', error.message);  
    throw error;  
  } finally {  
    console.log('finally block is run');  
  }  
} catch (error) {  
  console.error('outer catch block caught', error.message);  
}
```

As we can see, if we ran the code above, then we get the following logged in order: ‘error error’, ‘finally block is run’, and ‘outer catch block caught error’. This is because the inner `catch` block logged the exception thrown by `throw new Error(‘error’)` , but then after `console.error(‘error’, error.message);` is ran, we ran `throw error;` to throw the exception again. Then the inner `finally` block is run and then the rethrown exception is caught by the outer `catch` block which logged the `error` that was rethrown by the `throw error` statement in the inner `catch` block.

Since the code runs sequentially, we can run `return` statements at the end of a `try` block. For example, if we want to parse a JSON string into an object we we want to return an empty object if there’s an error parsing the string passed in, for example, when the string passed in isn’t a valid JSON string, then we can write the following code:

```javascript
const parseJSON = (str) => {  
  try {  
    return JSON.parse(str);  
  }  
  catch {  
    return {};  
  }  
}
```

In the code above, we run `JSON.parse` to parse the string and if it’s not valid JSON, then an exception will be thrown. If an exception is thrown, then the `catch` clause will be invokes to return an empty object. If `JSON.parse` successfully runs then the parsed JSON object will be returned. So if we run:

```
console.log(parseJSON(undefined));  
console.log(parseJSON('{"a": 1}'))
```

Then we get an empty object on the first line and we get `{a: 1}` on the second line.


Try Block in Asynchronous Code
==============================

With `async` and `await` , we can shorten promise code. Before `async` and `await`, we have to use the `then` function, we make to put callback functions as an argument of all of our `then` functions. This makes the code long is we have lots of promises. Instead, we can use the `async` and `await` syntax to replace the `then` and its associated callbacks as follows. Using the `async` and `await` syntax for chaining promises, we can also use `try` and `catch` blocks to catch rejected promises and handle rejected promises gracefully. For example , if we want to catch promise rejections with a `catch` block, we can do the following:

```javascript
(async () => {  
  try {  
    await new Promise((resolve, reject) => {  
      reject('error')  
    })  
  } 
  catch (error) {  
    console.log(error);  
  }
})();
```

In the code above, since we rejected the promise that we defined in the `try` block, the `catch` block caught the promise rejection and logged the error. So we should see ‘error’ logged when we run the code above. Even though it looks a regular `try...catch` block, it’s not, since this is an `async` function. An `async` function only returns promises, so we can’t return anything other than promises in the `try...catch` block. The `catch` block in an `async` function is just a shorthand for the `catch` function which is chained to the then function. So the code above is actually the same as:

```
(() => {  
  new Promise((resolve, reject) => {  
      reject('error')  
    })  
    .catch(error => console.log(error))  
})()
```

We see that we get the same console log output as the `async` function above when it’s run.

The `finally` block also works with the `try...catch` block in an `async` function. For example, we can write:

```javascript
(async () => {  
  try {  
    await new Promise((resolve, reject) => {  
      reject('error')  
    })  
  } catch (error) {  
    console.log(error);  
  } finally {  
    console.log('finally is run');  
  }  
})();
```

In the code above, since we rejected the promise that we defined in the `try` block, the `catch` block caught the promise rejection and logged the error. So we should see ‘error’ logged when we run the code above. The the `finally` block runs so that we get ‘finally is run’ logged. The `finally` block in an `async` function is the same as chaining the `finally` function to the end of a promise so the code above is equivalent to:

```javascript
(() => {  
  new Promise((resolve, reject) => {  
      reject('error')  
    })  
    .catch(error => console.log(error))  
    .finally(() => console.log('finally is run'))  
})()
```

We see that we get the same console log output as the `async` function above when it’s run.

The rules for nested `try...catch` we mentioned above still applies to `async` function, so we can write something like:

```javascript
(async () => {  
  try {  
    await new Promise((resolve, reject) => {  
      reject('outer error')  
    })  
    try {  
      await new Promise((resolve, reject) => {  
        reject('inner error')  
      })  
    } 
    catch (error) {  
      console.log(error);  
    } 
    finally { }  
  } 
  catch (error) {  
    console.log(error);  
  } 
  finally {  
    console.log('finally is run');  
  }  
})();
```

This lets us easily nest promises and handle their errors accordingly. This is cleaner than chaining the `then`, `catch` and `finally` functions that we did before we have `async` functions.

To handle errors in JavaScript programs, we can use the `try...catch...finally` blocks to catch errors. This can be done with synchronous or asynchronous code. We put the code that may throw exceptions in the `try` block, then put the code that handles the exceptions in the `catch` block. In the `finally` block we run any code that runs regardless of whether an exception is thrown. `async` functions can also use the `try...catch` block, but they only return promises like any other `async` function, but `try...catch...finally` blocks in normal functions can return anything.