Create Your Own Custom JS Error Type 🤔
Tags: webdev, javascript, errors
Published: 2021-03-19 18:18:59

If you are fairly new to programming, then it is very natural to feel that **Errors** are evil nasty things to be avoided at all costs. 

When an error happens, we are thankful that we have a `catch()` method or a `try...catch` block to stop our page from crashing. We `log` the error message to the console and move on to more important less stress-inducing things.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xz5mvm1hc4ay28uf03s3.png)

Sometimes those message are red, sometimes amber, often cryptic or unnerving to the uninitiated novice.

## Taking control

Once you realize that every error message is actually meant to be a source of assistance from another developer, that fear can start to dissipate.

An error message is really another developer's best effort to give you some information that you can use to diagnose the cause of the problem.

If you are writing code, that means at some point another developer will be running the code that you wrote and a problem will occur. You should want to help that poor developer solve the problem.

## Fake it till you make it 

Why not start using the best practices of intermediate and senior developers now?

1. Start writing more detailed error messages. 
2. Start building your own types of Error objects.
3. Start intentionally generating Error objects in your code. 
4. Throw Errors and Catch them, on purpose.

## How to Create an Error

A basic Error object is actually quite easy to create.

```js
let err = new Error('This is my friendly message');
```

One line of code and now you have your very own `Error` object in a variable that you can pass around your code.

The `String` that we pass to the error constructor becomes the value of the `message` property in the `Error` object.

## How do I Throw an Error?

Just because you create an `Error` object and put it inside a variable does not mean that anything will happen with the error. If you want the browser to react to the error then you have to `throw` it.

Think of it as shooting a flare up into the air. If you want your error to be noticed, then we need to draw attention to it.

```js
let err = new Error('This is my friendly message');
throw err;
//or alternatively
throw new Error('This is my friendly message');
``` 

When you `throw` the error either your script crashes and writes out the message in the console, or we need to have a `try...catch` block or `catch( )` method ready to **catch** the thrown error.

Try out the following snippets to see you error messages appear in the console without crashing your script. You can run them directly in the browser console if you want.

#### try...catch

```js
try{
  throw new Error('This is my friendly message');
}catch(err){
  console.log(err.message);
}
```

#### catch( )

```js
Promise.resolve()
  .then( () => {
    throw new Error('This is my friendly message');
  })
  .catch( err => {
    console.log(err.message);
  });
```

## Create your Own Custom Error

While it is nice to be able to display a friendly message in the console, in the real world we have actual problems that happen in our code. 

We have situations that you are occasionally just using `if` statements to handle: A user has failed to provide their usernam; an invalid product reference code was entered in the querystring; there was a network failure when making an AJAX call; and many other every day situations.

We can create our own `type` of `Error` object for each of these. We can add additional information about the error into the `Error` object. We can `throw` and `catch` these errors to make our code more resistant to failure, as well as, providing more details to other developers.

This code can be made with or without the `class` keyword but I am going to show the `class` version here. I am going to create my own special type of error to use with `fetch()` calls that fail because the browser is offline.

```js
class NetworkError extends Error{
  constructor(msg, url){
    super(msg);
    this.name = 'NetworkError';
    this.target = url;
  }
}
```

My new Error type is going to be called `NetworkError`. It is going to inherit all the properties of a standard `Error` object. However, it is getting an extra property called `target` that will hold the `URL` which was being used when the failure occurred. 

## Use your Errors as Part of the Solution

So, we now have our own `NetworkError` type object that we can add to our JS files or put in a utilities file that we use in all our projects.

Let's put it into use as part of our project.

```js
document.body.addEventListener('click', (ev) => {

let url = `http://jsonplaceholder.typicode.com/users/10`;

fetch(url)
  .then((response) => {
    //we got a response from the server
    if(response.status == 404){
      throw new NetworkError(response.statusText, url);
    }
    //run more code on the response.
    return response.json();
  },
  (err)=>{
    //err is a general error happened with fetch( )
    //this is a network failure, usually meaning offline
    throw new NetworkError('Unable to reach server.', url);
  })
  .then((data) => {
    console.log(data);
  })
  .catch( err => {
    //err could be either of those NetworkErrors or
    //an error that happened in the `run more code on the response`
    //check for the type of error
    switch(err.name){
      case 'NetworkError':
        //handle our network errors.
        console.warn(`Dude. You were totally trying to access ${err.target}. And then the browser was all like ${err.message}`);
        break;
      default:
        //handle any other errors
        console.error(`At least it wasn't a Network error. ${err.message}`);
    }
  });

}
```

If you put all our script into a webpage, and then in the dev tools Network tab set the browser to offline.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y4ys3qc1x8vlv8u3jvyt.png)

Run the script once online and once with the browser tab toggled to offline and you should see our custom `NetworkError` messages in the console.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sg3c92zi3uesyukj5y1q.png)

I've wrapped a click event listener function around the `fetch()` call. You may have to add the following CSS to give you something to click.

```css
body {
  min-height: 100vh;
  background-color: #333;
  cursor: pointer;
}
```

If you want to learn more about Error handling, Javascript or practically any web development topic: please check out my [YouTube channel](https://www.youtube.com/c/SteveGriffith-Prof3ssorSt3v3/videos) for hundreds of video tutorials.