Monday 5 December 2016

JavaScript error handling async function passed to reduce



I'm passing an async function to an array reduce function. What's the syntax for catching errors thrown by the passed in function? The reducing is happening inside a try catch block, which is catching other errors just fine, but node gives me an UnhandledPromiseRejectionWarning if the passed in function itself throws an error.



Code:



aFunction = async (anArray) => {
try {
const result = await anArray.reduce(async (a, b) => {
await doSomethingTo(b);
}, Promise.resolve());

return result;
}

catch (error) {
winston.error(error);
}
}


(Edit) Actual code:



exports.chainedQueryDB = async (queries, finalTask, download) => {
let client = await pool.connect();
try {
winston.info(`Begin chained table query.`);
// Loop through query array
const result = await queries.reduce(async (a, b) => {
await client.query(b);
}, Promise.resolve());

if (download) {
return streamOut(download, client);
}

return result.rows;
}

catch (error) {
throw error;
}

finally {
const final = await client.query(finalTask);
winston.info(`Temp table dropped.`);
client.release();
}
}


(Edit) Report:
Replacing await client.query(b) with await a; return client.query(b); solved the problem. With just await client.query(b), reduce seemed to 1) generate a bunch of floating client.query calls that all ran even if an earlier promise was rejected, and 2) caused an unhandled promise rejection warning. Using await a; return client.query(b); stops execution on first rejection and the catch block catches the error as originally intended.


Answer



You need to do something with the promise in the accumulator (the a parameter) as well - await it, handle its errors by installing a .catch() callback, wait for it concurrently with the doSomething(b). For a sequential execution, you could do



async function aFunction(anArray) {
try {
return await anArray.reduce(async (a, b) => {
await a; // make sure the previous query is done
return doSomethingTo(b);
}, Promise.resolve());
} catch (error) {
winston.error(error);
}
}


I would hover recommend to simply not use reduce here:



async function aFunction(anArray) {
try {
let result;
for (const b of anArray) {
result = await doSomethingTo(b);
}
return result;
} catch (error) {
winston.error(error);
}
}

No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...