Try/Catch always needed for await?

# Jordan Rome (8 years ago)

My apologies if this has already been discussed but what is the "preferred" pattern for using await ? Since await, which runs on promises, will now throw if the promise is rejected (preventing execution of code after the await and killing the process in Node), is it neccesary to always be wrapping await in try/catch?

I don't wrap all my sync code (even when calling functions in an external dependency) in try/catch yet a lot of posts/articles I've seen written about await is that you should always wrap it in a try/catch. Is this because there is a lot of mis-use of reject, which, AFAIK, is supposed to contain an Error and is the async equivalent of throwing? Or maybe because you just don't know the source and length of the promise chain and therefore it's dangerous?

# Bergi (8 years ago)

Jordan Rome schrieb:

My apologies if this has already been discussed but what is the "preferred" pattern for using await ? Since await, which runs on promises, will now throw if the promise is rejected (preventing execution of code after the await and killing the process in Node), is it neccesary to always be wrapping await in try/catch?

No. Just like in synchronous code, you only wrap a part of your code in try-catch if you actually want to handle an exception.

If you don't handle it, it will bubble as usual and reject the promise returned by the async function. Let the caller deal with the exceptions you can't handle - just like always. Of course, in the top-level invocation it might be a good idea to use a catch (or the .catch() method) to catch any exceptions and log them to whereever you want if you don't want to get an unhandled rejection, but those are usually exceptions you don't expect so you might not need to deal with them at all.

# Alan Johnson (8 years ago)

To perhaps clarify this point a bit, it is very important to .catch() and react appropriately at the ends of promise chains. If synchronous code fails for an unexpected reason, a visible crash will definitely happen. This is not the case for promises, because there’s no way for the runtime to know whether that promise is just some middle step in the chain, in which case you’d want to propagate rejection, rather than throw a synchronous exception. Having unexpected errors be silently swallowed is definitely a problematic property of promises, which you have to guard against.

It probably would be possible for the runtime to report crashes of promises that have no registered .then(). The only problem is, it’s totally possible the programmer is going to attach a .then() or .catch() later on to a promise that has already failed. Some promise libraries offer a .done() that has the semantics of “crash if this promise rejects”. But arguably, this should be the normal behavior, with an opt-out instead, so that it is assumed that you want rejected promises without any .then()s to throw synchronous exceptions. Something like a .noFail() could opt out

# Andrea Giammarchi (8 years ago)

Just one thought:

Of course, in the top-level invocation it might be a good idea to use a catch

after years of engine developers advocating "avoid try/catch as much as possible because it de-opts and slow down code and JIT and you name it", above suggestion doesn't really look like an "of course".

Using a proper .catch() within the async returned promise is probably the best approach.

Best

# Jordan Rome (8 years ago)

On Fri, Oct 14, 2016 at 11:25 AM, Alan Johnson <alan at breakrs.com> wrote:

Having unexpected errors be silently swallowed is definitely a problematic property of promises, which you have to guard against.

I didn't think this was the case with await. If a promise rejection is not caught the await throws an exception and doesn't execute code below in the async function. Also, I believe Node is soon adding support for killing the process if a rejected Promise is not caught before it's garbage collected. If this is true why the importance of using try/catch with await, don't we want programmer errors to be noisy so we can fix them?

# Jordan Harband (8 years ago)

When the await throws an exception that's not caught by a try/catch, the promise returned by the async function ends up rejected - and you have the identical scenario as a promise with an unhandled rejection.

node has been discussing adding "crash on garbage collection of an unhandled rejection", but the reason this is possible for them to add is because by the time something gets garbage collected, nothing in JS can possibly add a later catch handler - and this would cover promises and async functions identically.

In other words, async/await in no way whatsoever changes the discussion around unhandled promise rejections.

# Jordan Rome (8 years ago)

On Sat, Oct 15, 2016 at 11:40 PM, Jordan Harband <ljharb at gmail.com> wrote:

When the await throws an exception that's not caught by a try/catch, the promise returned by the async function ends up rejected - and you have the identical scenario as a promise with an unhandled rejection.

Ah, that's the part I was missing and that 'await' is not allowed at the top level (for now). Thanks!

I think then my question really depends on the implementation of unhandled rejections? I see a lot of example code where 'catch' simply calls console.error (and/or logs an error to a backend). In chrome you get the 'Uncaught (in promise)' message in the console. I'm still confused as to why it's important to always try/catch (or even catch for promises) if you get an error message in the console (vs calling console.error manually). Do some engines still silently swallow these errors without any kind of notice?

# Marky Mark (8 years ago)

On Sun, Oct 16, 2016, 5:32 AM Jordan Rome <jordan at jordanrome.com> wrote:

I'm still confused as to why it's important to always try/catch (or even catch for promises) if you get an error message in the console (vs calling console.error manually).

You don't always have to catch promise errors. It's entirely optional and depends on your needs.Why do you think you always have to? But if you dont, your program will never know about the error or do anything to handle it.

--

mark

Sent while riding a hoverboard... heyimmark.com :)

# Jordan Rome (8 years ago)

On Sun, Oct 16, 2016 at 9:14 AM, Marky Mark <mark at heyimmark.com> wrote:

But if you dont, your program will never know about the error or do anything to handle it.

Perhaps this is where I'm confused. I'm under the impression that catch shouldn't be used anymore than try/catch does when you're writing synchronous code. I usually end up using try/catch only when there is a higher likelihood of programmer error (e.g. JSON.parse). If my program happens to throw, I don't just wrap that bit of code in another try/catch but I go and fix whatever was causing the throw (if fixable). I don't quite see how this changes with Promises or async code in general as I see a lot of folks adding catch and wrapping await in try/catch -- claiming that it's* "very important" *to do this (quoting Alan above). Perhaps this is from a time when Promises were swallowing errors and not reporting unhandled rejections but it seems like browsers and node are fixing or have fixed this issue. So, if my Promise chain rejects and I have not caught it, I would just go in and fix whatever was throwing/rejecting (again, if fixable).

# Jordan Harband (8 years ago)

Just because you get a message in your console that you have an unhandled rejection, doesn't mean your program can adapt to that as needed. Relying on that information is a last resort - it's the final safety net for you, the human, if you've failed to .catch all your promises at runtime (in your code).