async.parallel 到异步等待 - Node.js
async.parallel to async await - Node.js
我正在使用 express-promise-router 在来自 node.js 的查询调用中实现 async/await。有时,当我需要为表获取数据时,我使用 async.parallel 来获取数据以及计数作为单独的数据并将它们合并。我在这里使用回调。我如何继续为这些使用 async/await?
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 = {};
async.parallel({
rows: (cb) => {
pool.query(
query,
(err, data) => {
if (!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)
}
cb(err, result)
})
},
count: (cb) => pool.query(
countQuery,
(err, data) => {
if (!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)
}
cb(err, result);
})
}, (err, result) => {
if (err) {
result.error = err.message;
}
response.json(result.rows)
})
});
我试图使代码与上面的代码相似,但最后我注意到您正在使用更高级别的 result
对象来传递引用。
在下面的代码中,我没有使用 async/await
因为对于这个例子来说这不是完全必要的,因为 pool.query
方法需要一个回调。相反,我创建了 rows
和 count
函数 return Promises。然后我使用带有 Promise.all
的那些,这将使两个承诺 运行 并行,并且 return 结果作为数组按照承诺传递给 Promise.all
的相同顺序。当 pool.query
return 是一个承诺时,请参阅使用 async/await
的示例。
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
});
function rows() {
return new Promise((resolve, reject) => {
pool.query(
query,
(err, data) => {
if (err) {
return reject(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);
});
});
}
function count() {
return new Promise((resolve, reject) => {
pool.query(
countQuery,
(err, data) => {
if (err) {
return reject(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);
});
});
}
});
下一个示例显示使用 async/await
假设 pool.query
可以 return Promise。我还假设对象引用仍将被维护,这就是为什么我在 try/catch
.
的 try
部分分配 result.rows = results[0]
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 = `select count(*) 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;
}
});
我希望这可以帮助您了解如何使用 async/await
进行并行处理。我看到您的代码中可能出现的唯一问题是 rows
查询 return 是否在 count
查询之前,因为 totalItem
尚未设置。
编辑:就个人而言,我认为我会用 1 个查询而不是 2 个不同的查询来处理这样的逻辑:
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);
});
编辑 2:在评论中进行更多讨论后,我认为这个版本会更好用。它不使用主 result
对象来提供引用,而是将基于 "count" 的属性移动到 count
函数以允许并行执行:
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 = `select count(*) 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 scope
const 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;
}
});
我正在使用 express-promise-router 在来自 node.js 的查询调用中实现 async/await。有时,当我需要为表获取数据时,我使用 async.parallel 来获取数据以及计数作为单独的数据并将它们合并。我在这里使用回调。我如何继续为这些使用 async/await?
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 = {};
async.parallel({
rows: (cb) => {
pool.query(
query,
(err, data) => {
if (!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)
}
cb(err, result)
})
},
count: (cb) => pool.query(
countQuery,
(err, data) => {
if (!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)
}
cb(err, result);
})
}, (err, result) => {
if (err) {
result.error = err.message;
}
response.json(result.rows)
})
});
我试图使代码与上面的代码相似,但最后我注意到您正在使用更高级别的 result
对象来传递引用。
在下面的代码中,我没有使用 async/await
因为对于这个例子来说这不是完全必要的,因为 pool.query
方法需要一个回调。相反,我创建了 rows
和 count
函数 return Promises。然后我使用带有 Promise.all
的那些,这将使两个承诺 运行 并行,并且 return 结果作为数组按照承诺传递给 Promise.all
的相同顺序。当 pool.query
return 是一个承诺时,请参阅使用 async/await
的示例。
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
});
function rows() {
return new Promise((resolve, reject) => {
pool.query(
query,
(err, data) => {
if (err) {
return reject(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);
});
});
}
function count() {
return new Promise((resolve, reject) => {
pool.query(
countQuery,
(err, data) => {
if (err) {
return reject(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);
});
});
}
});
下一个示例显示使用 async/await
假设 pool.query
可以 return Promise。我还假设对象引用仍将被维护,这就是为什么我在 try/catch
.
try
部分分配 result.rows = results[0]
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 = `select count(*) 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;
}
});
我希望这可以帮助您了解如何使用 async/await
进行并行处理。我看到您的代码中可能出现的唯一问题是 rows
查询 return 是否在 count
查询之前,因为 totalItem
尚未设置。
编辑:就个人而言,我认为我会用 1 个查询而不是 2 个不同的查询来处理这样的逻辑:
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);
});
编辑 2:在评论中进行更多讨论后,我认为这个版本会更好用。它不使用主 result
对象来提供引用,而是将基于 "count" 的属性移动到 count
函数以允许并行执行:
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 = `select count(*) 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 scope
const 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;
}
});