When I run the following code, why do I get unhandled promise rejection warning?
async function load() {
throw new Error('error');
}
async function main() {
const promise = load();
await new Promise(resolve => setTimeout(resolve, 5000));
try {
await promise;
} catch (e) {
console.log('caught error', e);
}
}
main();
This is the output:
jkim@dev-jkim test $ node index.js
(node:25276) UnhandledPromiseRejectionWarning: Error: error
Since await promise
is around a try-catch, I'm confused why my try-catch isn't catching the error. I guess it's something to do with the setTimeout
since the following code works:
async function load() {
throw new Error('error');
}
async function main() {
const promise = load();
try {
await promise;
} catch (e) {
console.log('caught error', e);
}
}
main();
jkim@dev-jkim test $ node index.js
caught error Error: error
What is going on here? If promise rejections are not handled by the end of the current tick, does it automatically result in a unhandled promise rejection warning?
(I'm on node v10.16.3)
If promise rejections are not handled by the end of the current tick, does it automatically result in a unhandled promise rejection warning?
Yes. A Promise must have a rejection handler attached to it at the moment it rejects, or the rejection will count as unhandled. If you attach the rejection handler later, such as after a
await new Promise(resolve => setTimeout(resolve, 5000));
the load
Promise has rejected by the time the interpreter gets to the
try {
await promise;
} catch (e) {
so, although the rejection can be caught with .catch
, it wasn't caught by anything at the moment of rejection, resulting in the warning.
Best practice for this sort of thing is to always attach a rejection handler immediately - whether that means .catch
, or inside a try
/catch
, or a Promise.all
, or returning the Promise for the caller to handle.