Reputation: 9437
In my app.js
I have the following...
app.use(async (ctx, next) => {
try {
await next()
} catch (err) {
ctx.status = 400
ctx.body = `Uh-oh: ${err.message}`
console.log('Error handler:', err.message)
}
});
app.use(router());
Then in routes
I have defined...
router.post('/', retrieve);
The logic for retrieve is structured as so...
const retrieve = async ctx => {
Object.keys(ctx.request.files).forEach((key) => {
process(files[key]);
});
};
Now let's say I throw an error in retrieve
...
const retrieve = async ctx => {
throw new Error(`Error!`);
Object.keys(ctx.request.files).forEach((key) => {
process(files[key]);
});
};
This will work correctly and bubble up all the way to app.js
. However, the process
function is also using async
, if I throw the error there instead...
const retrieve = async ctx => {
Object.keys(ctx.request.files).forEach((key) => {
process(files[key]);
});
};
const process = async (file) => {
throw new Error(`Error!`);
...
I get the following error...
UnhandledPromiseRejectionWarning: Error: Error!
Why am I getting UnhandledPromiseRejectionWarning
? How can I fix it and make it so that any error thrown inside of process
gets bubbled up to app.js
?
Upvotes: 0
Views: 309
Reputation: 85
As the forEach loop is not async, the errors get thrown after it's execution and are therefore not able to bubble up to app.js. Now there are two solutions to it, either you can use a for
loop, or map the promises and wait for all of them to resolve. Sample code according to your problem :
process
sequentiallyconst retrieve = async ctx => {
const ctxKeys = Object.keys(ctx.request.files);
for(let i = 0 ; i < ctxKeys.length ;++i){
await process(files[ctxKeys[i]]);
}
};
process
asynchronouslyconst retrieve = async ctx => {
await Promise.all(Object.keys(ctx.request.files).map(async (key) => {
await process(files[key]);
}));
};
Upvotes: 1