我正在使用express和npm MySQL开发API。我有一个json请求,格式如下:
{
"payments":[
{
"PolicyNo": "ME3",
"PaymentDate": "2019-04-16T18:00:00.000Z",
},
{
"PolicyNo": "PIN001q",
"PaymentDate": "2019-04-16T18:00:00.000Z",
}]
}
我想在插入之前检查数据库是否存在policyNo。为了避免常见的ERR_HTTP_HEADERS_SENT,我遍历了使用PolicyNo查询数据库的付款。如果存在,则将其推送到成功数组中;如果不存在,则将其推送到失败数组中。 这可以完美工作,但是我无法在回调之外访问这些数组。 这是我尝试过的:
router.post('/bla', (req, res)=>{
const values = []
const failedvalues = []
let sql = 'SELECT PolicyNo from pinclientinfo WHERE PolicyNo=?'
req.body.payments.forEach(element => {
connection.query(sql,element.PolicyNo,(err, rows) =>{
if(!err){
if(rows && rows.length > 0){
values.push(element.PolicyNo, element.PaymentDate)
}else{
failedvalues.push(element.PolicyNo)
}
}
})
})
res.json({
failed:failedvalues,
success:values
})
})
这是我得到的答复:
{
"failed": [],
"success": []
}
答案 0 :(得分:0)
这有一些主要问题,主要是在概念上。
首先forEach
是同步的,将被多次调用payments.length
,但是sql查询是异步的,因此它将在将来完成。
我认为您对同步和异步功能及其工作方式感到困惑。
但是您可以(至少在两种情况下)解决此问题。
1)使用IN语法并获取数组。遍历它并做一些事情。 "SELECT PolicyNo from pinclientinfo WHERE PolicyNo in (...)"
let sql = 'SELECT PolicyNo from pinclientinfo WHERE PolicyNo IN (' + Array(req.body.payments).fill('?').join(',') + ')'
const policies = req.body.payments.map(p => p.PolicyNo);
const values = [];
const failedvalues = [];
connection.query(sql, ...policies, (err, rows) => {
//now check each row..
rows.forEach(element => {
//Not optimized only depicts logic
///do stuff
/// like fill values and failedvalues
if(policies.indexOf(element.PolicyNo) > -1){
values.push(...)
}else{
failedvalues.push(...)
}
});
res.json({
failed: failedvalues,
success: values
})
})
这将是1个数据库调用。
2)另一种方法是(不是很好)执行多个数据库调用并检查计数。
let sql = 'SELECT PolicyNo from pinclientinfo WHERE PolicyNo=?'
let count = 0;
req.body.payments.forEach(element => {
connection.query(sql, element.PolicyNo, (err, rows) => {
if (!err) {
if (rows && rows.length > 0) {
values.push(element.PolicyNo, element.PaymentDate)
} else {
failedvalues.push(element.PolicyNo)
}
}
// check If all Complete
count+=1;
if(count === req.body.payments){
//all complete
res.json({
failed: failedvalues,
success: values
})
}
})
})
请认真使用PROMISE
。使用ASYNC/AWAIT
使用这些甜美的小功能ES6为您提供
签出:this post
答案 1 :(得分:0)
因为connection.query是异步的,所以返回:
{
"failed": [],
"success": []
}
使用promise
和await
可以同步解析mysql数据
使用Promise.all()
,您可以同步解决承诺清单
router.post("/bla", async (req, res) => {
let values = [];
let failedvalues;
let promises = [];
let sql = "SELECT PolicyNo from pinclientinfo WHERE PolicyNo=?";
req.body.payments.forEach(element => {
promises.push(
new Promise(function(resolve, reject) {
connection.query(sql, element.PolicyNo, (err, rows) => {
if (!err) {
if (rows && rows.length > 0) {
values.push(element.PolicyNo, element.PaymentDate);
} else {
failedvalues.push(element.PolicyNo);
}
}
resolve();
});
})
);
});
await Promise.all(promises);
res.json({
failed: failedvalues,
success: values
});
});