JavaScript: Handling errors like Go
Tags: javascript, webdev, node, programming
Published: 2018-11-08 01:00:38

---
title: JavaScript: Handling errors like Go
published: true
description: How async/await help us isolate our error handling
tags: javascript,webdev,node,programming
cover_image: https://thepracticaldev.s3.amazonaws.com/i/2qh4ngkezzm28uytbkqv.png
---

Back in August, I wrote an [article in Brazilian-Portuguese](https://medium.com/@oieduardorabelo/javascript-tratando-erros-ao-estilo-go-65c5da9c12a9) explaining how I use `async`/`await` to isolate error handling.

Today I'll translate it to English but with different examples!

---

I love how [Go](http://golang.org/) handle side-effects in a synchronous-like manner. Let's see this example from the `net/http` package:

```go
func main() {
  res, err := http.Get("http://example.com/")

  if err != nil {
    // handle `err`
  }

  // do something with `res`
}
```

Or perhaps the `os` package:

```go
func main() {
  file, err := os.Open("words.txt")

  if err != nil {
    // handle `err`
  }

  // do something with `file`
}
```

Implementation details aside, I was wondering if there's a way to write something like this in JavaScript?

Well, as they say, where there's a will, there's a way! 😂

# Everyday Promise-like functions

Nowadays Promise-like environments are common amongst us.

We can use it to read a file in Node.js:

```js
let util = require("util");
let fs = require("fs");

let read = util.promisify(fs.readFile);

function main() {
  read("./test.js", { encoding: "utf8" })
    .then(file => {
      // do something with `file`
    })
    .catch(err => {
      // handle `err`
    });
}

main();
```

Perhaps fetching some data from an API:

```js
let url = "https://dog.ceo/api/breeds/image/random";

function main() {
  fetch(url)
    .then(res => res.json())
    .then(res => {
      // do something with `res`
    })
    .catch(err => {
      // handle `err`
    });
}

main();
```

And being lazy by nature, we create functions to hide some boilerplate for us, so we can write less code across the codebase:

```js
let readFile = require("./readFile");

function main() {
  readFile("./test.js")
    .then(file => {
      // do something with `file`
    })
    .catch(err => {
      // handle `err`
    });
}

main();


// readFile.js
let util = require("util");
let fs = require("fs");

let read = util.promisify(fs.readFile);

module.exports = path => {
  return read(path, { encoding: "utf8" })
    .then(file => {
      return file;
    })
    .catch(err => {
      throw err;
    });
};
```

And:

```js
let api = require("./api");

function main() {
  api.getRandomDog()
    .then(res => {
      // do something with `res`
    })
    .catch(err => {
      // handle `err`
    });
}

main();


// api.js
let url = "https://dog.ceo/api/breeds/image/random";

let api = {};

api.getRandomDog = () => {
  return fetch(url)
    .then(res => res.json())
    .catch(err => {
      throw err;
    });
};

module.exports = api;
```

Still, there's a lot of repetition here, there's `.then` and `.catch` in both sides  of this code snippet.

They say `async`/`await` can fix this, so...let's try it then?

# Converting to `async`/`await`

Let's see how our Node.js is doing in `async`/`await`:

```js
let readFile = require("./readFile");

async function main() {
  try {
    let res = await readFile("./test.js");
    // do something with `file`
  } catch (err) {
    // handle `err`
  }
}

main();


// readFile.js
let util = require("util");
let fs = require("fs");

let read = util.promisify(fs.readFile);

module.exports = async path => {
  try {
    let res = await read(path, { encoding: "utf8" });
    return res;
  } catch (err) {
    throw err;
  }
};
```

And how can we fetch our dog with it:

```js
let api = require("./api");

async function main() {
  try {
    let res = await api.getRandomDog();
    // do something with `res`
  } catch (err) {
    // handle `err`
  }
}

main();

// api.js
let url = "https://dog.ceo/api/breeds/image/random";

let api = {};

api.getRandomDog = async () => {
  try {
    let res = await fetch(url);
    let json = await res.json();
    return json;
  } catch (err) {
    throw err;
  }
};

module.exports = api;
```

Phew... I think we changed a problem by another. Now there's `try...catch` in both places. Thinking about our current interface between consumer/service, we've:

1. In our `main()` function we're calling a "service" (**readFile** and **api.**)
2. Our "service" function returns a `Promise`
3. When fulfilled, our service **returns** a payload
4. When rejected, our service **throw** an error

Hmm... perhaps this is the problem! Our interface between consumer/service are **different** for fulfilled and rejected scenarios.

Refreshing our memory about our [Go](http://golang.org/) example at the top:

```go
 func main() {
  res, err := http.Get("http://example.com/")

  if err != nil {
    // handle `err`
  }

  // do something with `res`
}
```

Seems we've the **same interface** for both, fulfilled and rejected scenario!

Let's try that with our last `async`/`await` example!

# Unified return interface with `async`/`await`

In our Node.js example:

```js
let readFile = require("./readFile");

async function main() {
  let [err, file] = await readFile("./test.js");

  if (err) {
    // handle `err`
  }

  // do something with `file`
}

main();


// readFile.js
let util = require("util");
let fs = require("fs");

let read = util.promisify(fs.readFile);

module.exports = async path => {
  try {
    let res = await read(path, { encoding: "utf8" });
    return [null, res];
  } catch (err) {
    return [err, null]
  }
};
```

And our Fetch API:

```js
let api = require("./api");

async function main() {
  let [err, res] = await api.getRandomDog();

  if (err) {
    // handle `err`
  }

  // do something with `res`
}

main();

// api.js
let url = "https://dog.ceo/api/breeds/image/random";

let api = {};

api.getRandomDog = async () => {
  try {
    let res = await fetch(url);
    let json = await res.json();
    return [null, json];
  } catch (err) {
    return [err, null]
  }
};

module.exports = api;
```

Well done!! 🎉🎉🎉

That's exactly what we were looking for! Our `main()` function looks like our Go example and now we've isolated all `try...catch` in our "service" functions.

Using this approach you can clean up your Node.js Middlewares/Controllers and in your Front-end, let's say with React/Redux, clean up `redux-thunks` or `redux-saga` functions/generators.

You can also unit test these "service" functions in isolation and guarantee they are returning the expected interface/data.