Let's Clean Up: Ugly Try-Catches!
Tags: javascript, typescript, refactor, cleancode
Published: 2019-11-30 10:58:27

# Let's Clean Up: Ugly Try-Catches!

We've all been there. We have all used `await` on `async` methods, forgetting to wrap them in `try-catch` just to be told off about an `Unhandled Error` 😱

But it's not just these `aysnc` methods that might throw. Perhaps we use a third-party library that throws, or we design our codebase in such a way that we throw errors intentionally to bubble error handling up a few layers.

So we proceed by wrapping our calls to the throwable methods in our `try-catch` blocks.  
Perfect! 😍

🤔 Or is it?

Working in a code base where you can expect methods to `throw` can lead to situations where your logic is wrapped in `try-catch` blocks. It also leads to other code design problems.

Take a look at the examples below:

```js
try {
  const myVar = myThrowableMethod();
} catch (err) {
  console.log(err);
}

// Wait, there's an error here:
console.log(myVar);

// myVar doesn't exist outside of the try scope.
```

As we can see above, the `myVar` variable doesn't exist outside of the `try` block. But we need that value to continue our logic!!

So now we need to do something a little different.
How about:

```js
try {
  const myVar = myThrowableMethod();
  const newVar = manipulateMyVar(myVar);
  const response = sendApiRequest(newVar);
  return respponse;
} catch (err) {
  console.log(err);
}
```

## 🤮!

No. Let's not do this.  
Now all our logic wrapped inside the `try` block. That's ugly.
Also, if any of the subsequent method calls throw, are we sure we want to handle them the same way!? Possibly, but most likely not!

Ok, let's try something else...

```js
let myVar;

try {
  myVar = myThrowableMethod();
  return respponse;
} catch (err) {
  console.log(err);
}

const newVar = manipulateMyVar(myVar);
const response = sendApiRequest(newVar);
```

This is a little better, but still not perfect. It's still ugly as `myVar` has to be declared then initialised almost immediately after just in a different scope. It also presents an issue when `myThrowableMethod` does throw, as execution will continue and try to use `myVar`!

🐛 Alert!

I could keep going, giving more situations where these `try-catch` blocks can present code design, readability, and maintainability problems.

Instead, I'll present you with a solution!

## The Solution 🚀

I wrote a small library to tackle this issue head on :

### Let's welcome [no-try](https://github.com/coly010/notry.git) to the scene. 🎉

## What is `no-try`? 😱

`no-try` is a tiny library that takes the `try-catch` out of your code, improves the readability and maintainability of your code whilst helping to improve code design.

It exposes two functions. `noTry` and `noTryAsync` with the latter resolving and returning the result of Promises.

Don't believe me? Let's look at it in more detail.

To install it, simply run `npm i --save no-try`  
Then add it to your file:

In TypeScript;

```ts
import { noTry } from "no-try";
```

In JS:

```js
const noTry = require("no-try").noTry;
```

Now, let's refactor our example above to use `no-try`.

```js
const { result, error } = noTry(() => myThrowableMethod());
if (error) {
  // Handle error
  return;
}

const newVar = manipulateMyVar(result);
const response = sendApiRequest(newVar);
```

🎉🎉🎉  
Isn't that cleaner!?

If you have a standard error handling function, you can supply that to `noTry` and it will invoke it for you if an error occurs!

```js
function myCustomErrHandler(error) {
  // Do something to handle error
}

const { result, error } = noTry(() => myThrowableMethod(), myCustomErrHandler);

if (error) {
  return;
}

const newVar = manipulateMyVar(result);
const response = sendApiRequest(newVar);
```

And that's it!

We've removed the `try-catch` blocks from our code, preventing issues relating to block-scoped variables, whilst also allowing our code to be much more readable without sacrificing the flexibility of handling the error how we want.

You can read more on `no-try` over on [GitHub](https://github.com/coly010/notry.git).

Now go clean your code!

---

If you have any questions, feel free to ask below or reach out to me on Twitter: [@FerryColum](https://twitter.com/FerryColum).