https://advancedweb.hu/how-to-avoid-uncaught-async-errors-in-javascript/
Exceptions, whether sync or async, go up the stack until there is a try..catch
to handle them. If there is no handler on any level, they become uncaught exceptions. Browsers and NodeJs both show them prominently on the console with an Uncaught Error: <msg>
or a (node:29493) UnhandledPromiseRejectionWarning: Error: <msg>
.
Besides their visibility, in some cases it’s sensible to restart an app when there is an uncaught error. It is a best practice to handle all errors in the code and not allow any to bubble up too much.
While uncaught errors work the same in sync and async functions, I’ve found that it’s easier to have an uncaught exception with async functions than with synchronous ones.
In this article, you’ll learn about a few cases where async exceptions bubble up and become uncaught errors. You’ll learn why they happen and what to do with them.
For example, let’s see the simplest async function, an async IIFE:
(async () => {
throw new Error("err"); // uncaught
})();
First, let’s see how a synchronous function works with a try..catch
block:
try {
(() => {
throw new Error("err");
})();
}catch(e) {
console.log(e); // caught
}
The console shows the error is handled by the catch block:
Error: err
Let’s change it to an async function:
try {
(async () => {
throw new Error("err"); // uncaught
})();
}catch(e) {
console.log(e)
}
The catch won’t run in this case:
Uncaught (in promise) Error: err
Why is that?
In the synchronous case, the error was a sync error, so the sync try..catch
could handle it. More simplified, the program execution never left the try..catch
block, so any errors were handled by it.