0

I'm trying to find a general way to handle errors on promise chains. In the following snipped I'd like to handle an potential connection-error directly in my connection.js.

connection.js

function getData() {
  return fetch(myEndpoint)
   .catch(err => handleConnectionError(err)) // redirect to error page or similar
}

app.js

// import connection
connection.getData()
  .then(data => handleData(data.foo))

So there are two ways this scenario could play out:

  • If I catch the error in connection.js without throwing a new one, it will continue the promise chain and handleData() will fail
  • If I throw an Error again after handling it, the Promise chain wont be executed any further, but then I have an unhandled-promise-rejection error in the console.

So is there actually no better way, than catching and handling the errors everytime I'm using the getData() function somewhere in my app?

Seltsam
  • 854
  • 1
  • 7
  • 27
  • Are you looking for something like this? https://stackoverflow.com/questions/31424561/wait-until-all-es6-promises-complete-even-rejected-promises `.then(({ data }) => { if (data) handleData(data.foo); ...` or maybe use `await` and `return` early if there's no `data` – CertainPerformance Nov 24 '18 at 07:50
  • Thats probably worse than actually handling the error every time i use the connection. But this is sadly just confirming, that there is no native way to handle this more elegantly. :-/ – Seltsam Nov 24 '18 at 07:53
  • `const { data } = await connection.getData(); if (!data) return;` seems reasonably clean IMO, though it's unfortunate that you'd have to use that in all consumers of `getData`, I wonder if there's a nicer way – CertainPerformance Nov 24 '18 at 07:57
  • I had an idea, if you don't like the `await` / `return`, use a callback you can call `.then` on. It looks odd but it reduces duplicated catch code https://jsfiddle.net/m0wheoa1/ – CertainPerformance Nov 24 '18 at 08:32
  • You could possibly return a new promise in getData, and reject it if there's an error. That should stop execution while not bubbling any errors up, though it will also require some extra work. Not sure if it's acceptable by your definition of native. – Burak Nov 24 '18 at 08:33
  • @Burak It seems like this could actually work while keeping it simple. https://jsfiddle.net/ue76gn9q/1/ Am I wrong? – Seltsam Nov 24 '18 at 09:52

2 Answers2

0

The best way to go about this would be to have a final catch to take care of all errors. E.G:

function errorHandler(e) {
    if (e instanceof x) {
        //handle here
    }
}

And then:

fetch(endPoint).then(doSomething).then(doAnotherThing).catch(err => errorHandler(err))

If fetch or any other promise along the chain produces an error, the rest of the then() statements will be skipped and will be catched by the final catch function. From there you will need to make sure that all types of errors that could be thrown by all promises are taken care of.

However, you will need to get rid of the catch in getData as it will cause the rest of the chain to run as usual since the error is taken care of.

Hope that helps

Burak
  • 73
  • 6
0

So is there actually no better way, than catching and handling the errors everytime I'm using the getData() function somewhere in my app?

Yes, that's precisely what you should do:

function getData() {
  return fetch(myEndpoint)
}

// elsewhere:
connection.getData().then(handleData, handleConnectionError);

You usually don't know whether you always want to "redirect to error page or similar". Maybe at some places in your app, you can handle connection errors by faking response data, and in other places you might want to show an error message instead of triggering a redirect.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375