javascript - async.parallel 到异步等待 - Node.js
问题描述
我正在使用 express-promise-router 在来自 node.js 的查询调用中实现异步/等待。有时,当我需要为表获取数据时,我使用 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
方法需要一个回调。相反,我创建了返回 Promisesrows
的count
函数。然后我使用那些Promise.all
可以让两个 Promise 并行运行并将结果作为数组以与 Promise 传递给的顺序相同的顺序返回Promise.all
。请参阅下面的示例,以查看使用async/await
whenpool.query
返回承诺的示例。
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
可以返回一个 Promise。我还假设对象引用仍将被维护,这就是我result.rows = results[0]
在.try
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 = `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
查询之前返回,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
函数以允许并行执行:
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;
}
});
推荐阅读
- reactjs - 使用效果中嵌套异步调用的反应测试
- ios - 从 UIImagePickerController 禁用裁剪和压缩视频
- perl - 使用 AES-256 使用 snmpv3 凭据访问设备时在 Net::SNMP 上启动会话时未获得响应
- python - 如何在 cython 中显示图像,不仅是黑色或白色,而且是我想要的任何颜色?
- r - lintr 包 - 在没有 roxygen 文档的情况下进行检查
- python - 如何使用 Python HTTP2 请求?
- angular - mat-radio-button 没有在 mat-menu 内获得焦点
- python - Imputer 和 MinMaxScaler 错误:TypeError
- sql - 使用 knex 从邮政编码中获取最近的地标
- python - 当输入为n时,多项式输出形式为“x^n + an-1*x + a0”