Async.parallel To Async Await - Node.js
Solution 1:
I tried to keep the code similar to what you have above, but I noticed at the end that you're using a higher level result
object to pass references around.
In the below code, I'm not using async/await
since that's not entirely necessary for this example since the pool.query
method takes a callback. Instead, I created rows
and count
functions that return Promises. Then I use those with Promise.all
which will let both promises run in parallel and return the results as an array in the same order the promises are passed to Promise.all
. See further down for an example using async/await
when pool.query
returns a promise instead.
router.post('/getDetail', (request, response, next) => {
const id = request.body.id;
const numPerPage = request.body.pSize;
const pageNum = request.body.pIndex;
let query = `select id,name,title,group_desc,unit_code from table1
where id = '${id}'`;
let countQuery = `select count(*) total_item from
(select id,name,title,group_desc,unit_code from table1
where id = '${id}') a`;
const result = {};
Promise.all([
rows(),
count()
])
.then(results => {
// results is an array and the first item is `rows`
response.json(results[0]);
})
.catch(err => {
// handle error
});
functionrows() {
returnnewPromise((resolve, reject) => {
pool.query(
query,
(err, data) => {
if (err) {
returnreject(err);
}
result.dataRows = data.rows;
result.numPerPage = numPerPage;
result.pageNum = pageNum;
result.totalPage = Math.ceil(result.totalItem / numPerPage);
result.firstItem = (pageNum - 1) * numPerPage + 1;
result.lastItem = (pageNum * numPerPage > result.totalItem) ?
result.totalItem : (pageNum * numPerPage);
resolve(result);
});
});
}
functioncount() {
returnnewPromise((resolve, reject) => {
pool.query(
countQuery,
(err, data) => {
if (err) {
returnreject(err);
}
result.totalItem = parseInt(data.rows[0].total_item);
result.totalPage = Math.ceil(result.totalItem / numPerPage);
result.lastItem = (pageNum * numPerPage > result.totalItem) ?
result.totalItem : (pageNum * numPerPage);
resolve(result);
});
});
}
});
The next example shows using async/await
assuming pool.query
can return a Promise. I'm also making the assumption that the object references will still be maintained and is why I'm assigning result.rows = results[0]
in the try
part of the try/catch
.
router.post('/getDetail', async(request, response, next) => {
const id = request.body.id;
const numPerPage = request.body.pSize;
const pageNum = request.body.pIndex;
let query = `select id,name,title,group_desc,unit_code from table1
where id = '${id}'`;
let countQuery = `selectcount(*) total_item from
(select id,name,title,group_desc,unit_code from table1
where id = '${id}') a`;
const result = {};
try {
const results = await Promise.all([rows(), count()]);
// results is an array and the first item is `rows`
result.rows = results[0];
} catch (err) {
result.error = err.message;
}
response.json(result.rows);
async function rows() {
const data = await pool.query(query);
result.dataRows = data.rows;
result.numPerPage = numPerPage;
result.pageNum = pageNum;
result.totalPage = Math.ceil(result.totalItem / numPerPage);
result.firstItem = (pageNum - 1) * numPerPage + 1;
result.lastItem = (pageNum * numPerPage > result.totalItem)
? result.totalItem
: (pageNum * numPerPage);
return result;
}
async function count() {
const data = await pool.query(countQuery);
result.totalItem = parseInt(data.rows[0].total_item);
result.totalPage = Math.ceil(result.totalItem / numPerPage);
result.lastItem = (pageNum * numPerPage > result.totalItem)
? result.totalItem
: (pageNum * numPerPage);
return result;
}
});
I hope this helps you understand how you can do parallel processing with async/await
. The only issue I see that may come up in your code is if the rows
query returns before the count
query since totalItem
won't be set yet.
EDIT: personally, I think I would handle the logic like this with 1 query instead of 2 different queries:
router.post('/getDetail', async(request, response, next) => {
const id = request.body.id;
const numPerPage = request.body.pSize;
const pageNum = request.body.pIndex;
let query = `select id,name,title,group_desc,unit_code from table1
where id = '${id}'`;
const result = {};
try {
const data = await pool.query(query);
result.dataRows = data.rows;
result.totalItem = data.rows.length; // data might already have a property for this
result.numPerPage = numPerPage;
result.pageNum = pageNum;
result.totalPage = Math.ceil(result.totalItem / numPerPage);
result.firstItem = (pageNum - 1) * numPerPage + 1;
result.lastItem = (pageNum * numPerPage > result.totalItem)
? result.totalItem
: (pageNum * numPerPage);
} catch (err) {
result.error = err.message;
}
response.json(result);
});
EDIT 2: After more discussion in the comments, I think this version will work better. It doesn't use the main result
object to provide references and moves the "count" based properties to the count
function to allow for parallel execution:
router.post('/getDetail', async(request, response, next) => {
const id = request.body.id;
const numPerPage = request.body.pSize;
const pageNum = request.body.pIndex;
let query = `select id,name,title,group_desc,unit_code from table1
where id = '${id}'`;
let countQuery = `selectcount(*) total_item from
(select id,name,title,group_desc,unit_code from table1
where id = '${id}') a`;
let result = { numPerPage, pageNum };
try {
const results = await Promise.all([rows(), count()]);
// this will combine the properties from both results onto the `result` object
result = Object.assign({}, result, ...results);
} catch (err) {
result.error = err.message;
}
response.json(result);
async function rows() {
const data = await pool.query(query);
return { dataRows: data.rows };
}
async function count() {
const data = await pool.query(countQuery);
// redefining result here to be only used in this scopeconst result = {};
result.totalItem = parseInt(data.rows[0].total_item);
result.totalPage = Math.ceil(result.totalItem / numPerPage);
result.firstItem = (pageNum - 1) * numPerPage + 1;
result.lastItem = (pageNum * numPerPage > result.totalItem)
? result.totalItem
: (pageNum * numPerPage);
return result;
}
});
Post a Comment for "Async.parallel To Async Await - Node.js"