Edit: in summary this issue is regarding unhandledRejection
in node.js. I didn't expect a promise that was not awaited (but later fails) to crash the program - because I didn't realize that unhandledRejection
was being thrown & causing node.js to exit. Refreshing my understanding of unhandledRejection
I now realize that any promise anywhere in the program that is rejected without a catch() statement will throw unhandledRejection and exit the node.js process on default. Which doesn't make too much sense to me, but at least I understand why it's happening.
In the following code example, thisFailsLater initially returns successfully, but then throws an error some time later.
This results in runTest() passing the try/catch and moving on to the next await.
However, while waiting for the next await call, thisFailsLater then throws an error, which causes Node.JS to exit:
% node t.js
Throwing error in 2 seconds
thisFailsLater returned successfully
t.js:4
throw new Error('thrown error in thisFails()')
^
Error: thrown error in thisFails()
at thisFails (t.js:4:9)
This is something I didn't expect: it seems that an async function can initially return successfully, but then any async function called but not awaited within the function that throws after returning will then crash the Node.JS process.
Am I correct in how this works? And if so, how can I prevent Node.JS from exiting when thisFailsLater() throws 2 seconds after returning successfully? This completely breaks my understanding of how Promises work (can only be resolved or errored once).
Error reproduction:
async function thisFails() {
console.log('Throwing error in 2 seconds')
await new Promise((resolve) => setTimeout(resolve, 2e3));
throw new Error('thrown error in thisFails()')
}
async function thisFailsLater() {
try {
// NOTE: intentionally NOT awaiting this call here.
thisFails()
} catch (err) {
console.log('thisFailsLater caught error', err)
}
}
async function runTest() {
try {
await thisFailsLater()
} catch (err) {
console.error('runTest caught error', err)
}
console.log('thisFailsLater returned successfully')
await new Promise((resolve) => setTimeout(resolve, 3e3));
}
runTest().then(() => {
process.exit(0)
}).catch((err) => {
// NOTE: the error that Node.JS crashes with is NOT logged here!
console.error('Caught error in main()', err)
process.exit(1)
})