Error Handling in JavaScript - The Complete Guide

Error Handling in JavaScript - The Complete Guide

Errors or Exceptions are often ignored topics among programmers. Some people think if you're a good programmer you won't have errors. But error handling is an essential skill for any serious programmer to provide the best experience for your users, and in this article I'm going to cover everything you need to know about error handling in JavaScript.

Before we begin, you can code along with me on YouTube:

Error is a native constructor in JavaScript and we can instantiate it:

const error = new Error('something went wrong')

Now you get access to 3 properties of this error:

const error = new Error('something went wrong')

error.name // Error
error.message // something went wrong
error.stack // shows where the error happened in the call stack

But instantiating an error isn't useful for us. Instead we throw the error like this:

throw new Error('something went wrong')

JavaScript has many built-in constructors for errors:

  1. Generic Error as seen above

  2. SyntaxError: new SyntaxError

  3. Reference Error: new ReferenceError

These errors can be intentionally thrown by us as programmers, or they can be thrown because of some bug we have in our code when we execute it.

Now what happens when we throw an Error is that JavaScript will:

  1. stop executing the program

  2. go through the call stack from top to bottom to look for a catch statement that handles the error.

  3. if JavaScript doesn't find any catch statement, the execution of the program will stop, and that's a terrible experience for our users!

  4. if JavaScript finds a catch statement, the error will hopefully be handled correctly, and the program continues to execute after that catch statement.

So Error Handling is a way to prevent our apps from crashing by simply defining catch statements in the call stack to handle errors thrown somewhere in our program. Let's see how to implement that magical catch statement in both synchronous and asynchronous code.

Synchronous Error Handling

To handle synchronous errors, we use the try catch syntax:

try {
  console.log('working fine')
  throw new Error()
  console.log('this line is never reached :(')
} catch(error) {
  console.log('something bad happened')
}

console.log('continue executing')

Now the error will be handled by the catch statement and the program will continue executing, while in the case of throwing the error without a catch statement, the program will break and stop completely!

That's fine, but throwing errors in synchronous JavaScript isn't that common in the wild. What is more common is errors happening when we try to d asynchronous operations like accessing a database or fetching data from an API or something similar to that. In that case, we use a different approach to handle errors. Let me show you.

Asynchronous Error Handling

Asynchronous code includes both promises and async/await syntax. So let's see how to handle errors in both cases.

To demonstrate error handling in asynchronous code, I'm going to write a code that we assume is going to do asynchonous operations behind the scenes like creating a new user in a database and see how to handle that error in native promises syntax and the new cool async/await syntax.

Promises

In native promises syntax, we catch errors using the catch() method as the following example:

Promise.resolve('creating a new user in the database')
  .then((response) => {
    throw new Error('#1 fail');
    return response; // line never executes
  })
  .then((response) => {
    console.log(response);
  })
  .catch((err) => {
    console.log(err);
  });

console.log('continue executing')

Async/Await

In Async/await syntax, we catch errors using try/catch just like in synchronous code as the following example:

async function createUser() {
    try {
        await Promise.reject('failed to create a new user')
    } catch (err) {
        console.log(err)
    }
}
await createUser()

console.log('continue executing')

Real World Application of Error Handling

If you wish to see a real world scenario of professional error handling, I encourage you to check my other blog post: Error Handling in Node.js and TypeScript and I promise you that you will learn a powerful skill for your future career.