DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’» is a community of 963,673 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
Cover image for Error first pattern for JavaScript Async/Await
Dale L. Jefferson
Dale L. Jefferson

Posted on • Updated on • Originally published at dalejefferson.com

Error first pattern for JavaScript Async/Await

Dealing with errors is not fun. In this article, I will show you a pattern for dealing with errors in Async/Await. This pattern avoids the use of try/catch.

// Callback
fetch(URL, (error, response) => ...)

// Promise
fetch(URL).then((response) => ...).catch((error) => {})

// Async / await
try { fetch(URL) } catch (error) {}

Notice with callbacks you have no choice but to deal with the error, or at least feel guilty of not dealing with it.

The problem

async fetchData() {
    let json;

    try {
        const response = await fetch(URL)
        try {
             json = await response.json()
        } catch (error) {
             console.log("Parsing failed", error)
             return
        }
    } catch (error) {
        console.log("Request failed", error)
        return
    }

    const stars = json.stargazers_count
    this.setState({stars})
}

Yuck, I hope that disgusts you as it does me, exceptions should be exceptional, and there is nothing exceptional about connectivity issues on a mobile device, this is normal control flow.

Go To Statement Considered Harmfulβ€Š (Edsger Dijkstra - 1968)

I believe try / catch is a glorified Go To statement, execution stops and control jumps to the catch block. It should be used sparingly for exceptions not normal control flow.

So we have gone from explicate returned errors to throwing exceptions, this does not sound like progress.

A possible solution

async fetchData() {
    const [responseError, response] = await fetch(URL);

    if (responseError || !response) {
        console.log("Request failed", responseError)
        return
    }

    const [parseError, json] = await response.json()

    if (parseError || !json) {
        console.log("Request failed", parseError)
        return
    }

    const stars = json.stargazers_count
    this.setState({stars})
}

This uses array destructuring and since error is the first value it makes you think about handling errors. I’ve mixed Go error handling with NodeJS error first callbacks.

Implementation details

const errorFirstPromise = promise => {
  return new Promise(resolve => {
    return promise
      .then(result => {
        return resolve([null, result]);
      })
      .catch(error => {
        return resolve([error, null]);
      });
  });
};

Top comments (0)

This post blew up on DEV in 2020:

js visualized

πŸš€βš™οΈ JavaScript Visualized: the JavaScript Engine

As JavaScript devs, we usually don't have to deal with compilers ourselves. However, it's definitely good to know the basics of the JavaScript engine and see how it handles our human-friendly JS code, and turns it into something machines understand! πŸ₯³

Happy coding!