Есть ли способ передать значение из функции обратного вызова mysql во внешнюю функцию в Express? - PullRequest
0 голосов
/ 06 мая 2019

Я использую 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 голосов
/ 06 мая 2019

, поскольку 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
  });
});

0 голосов
/ 06 мая 2019

Это имеет некоторые серьезные проблемы, в основном в концептуальном плане.

Во-первых, 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 ДАЕТ ВАМ

Проверить: этот пост

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...