David Young
David Young

Reputation: 31

How to avoid nested error messages while using async/await caught errors?

I have seen the three following variants of throwing errors.

var response = await api.call()
    .catch((error) => {
        throw error;
    });

var response = await api.call()
    .catch((error) => {
        throw Error(error);
    });

var response = await api.call()
    .catch((error) => {
        throw new Error(error);
    });

I have tried throw new Error(error) but a chain of async functions passing down the error resulted in:

"Error: Error: Error: Actual error message"

Which of these is recommended?

Upvotes: 1

Views: 49

Answers (2)

Jonas Wilms
Jonas Wilms

Reputation: 138267

 throw Error(error);

that just works because JS always executes the native constructors as constructors, even if you call them as a function. That's like semicolon insertion, while it works, I would not recommend relying on it because it is confusing and might introduce unwanted side effects. Basically, if everything is working as expected it is the same as:

 throw new Error(error);

now that also makes little sense, as you lose the errors stack trace. When an error object gets constructed, a lot of information is collected about how the error happened, which is really useful for debugging. As the error constructor expects a string as the first argument, error gets cast to a string, it is basically:

 throw new Error(error.toString());

and by stringifying, you only keep the message and lose everything else. You get back an error that occurs at the line above, which hides the place where it originated from, whereas:

 throw error;

just passes the error up, which will preserve all the mandatory information.


For clarity, I personally prefer not to mix thenables and async / await, so I would do:

try {
  const response = await api.call()
} catch(error) {
    // Some logging, handling, etc.
    throw error;
}

If you can't handle the error properly and always rethrow, it is senseless, just don't try to catch it. Handle it somewhere up the call stack, where you can actually handle it.

Upvotes: 1

Nino Filiu
Nino Filiu

Reputation: 18493

None of them is recommended. If you can't handle an error, don't catch it. However, if you catch some errors, you should throw the error as is so as to preserve all the debugging information:

somePromise()
  .catch(reason => {
    if (/* some test about the error */) {
      // handles some errors
    } else {
      throw reason; // <- more on that on @JonasWilms' answer
    }
  })

Upvotes: 0

Related Questions