有没有一种方法可以将mysql回调函数中的值传递给express中的外部函数?

时间:2019-05-06 13:11:09

标签: mysql node.js express

我正在使用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": []
}

2 个答案:

答案 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": []
}

使用promiseawait可以同步解析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
  });
});