在for循环中承诺

时间:2019-07-25 18:09:22

标签: javascript node.js es6-promise

我试图使用承诺的mysql库进行一堆数据库的插入和选择。

问题是我必须使用for循环。

我的代码如下:

var partNumber = [],
        stageName = [],
        quantity = [],
        locationName = []
    var orderType, receiveDate, customerName

    pool.query(`select * from orderDetail where orderID = ${req.body.orderID} order by orderDetailID`)
        .then(mainrow => {

            for (let i = 0; i < mainrow.length; i++) {

                    quantity.push(mainrow[i].QtyShipped)
                     pool.query(`Select PartNumber from parts where partID = ${mainrow[i].PartID}`)

                    .then(rows => {
                        console.log(`here is 1`)
                        partNumber.push(rows[0].PartNumber)

                        return pool.query(`Select StageName from stages where StageID = ${mainrow[i].StageID}`)
                    })
                    .then(rows => {
                        console.log(`here is 2`)

                        return pool.query(`Select LocationName from locations where locationID =${mainrow[i].LocationID}`)
                    })
                    .then(rows=>{
                        console.log(` here is 3`)
                        locationName.push(rows[0].LocationName)

                        stageName.push(rows[0].LocationName)
                        orderType=mainrow[i].OrderType
                        receiveDate = mainrow[0].receiveDate
                        req.flash('success', `You returned back to the OrderID ${req.body.orderID}`)
                        customerName = mainrow[0].CustomerName
                        if(i==mainrow.length-1){
                            var query = queryString.stringify({
                                "orderID": req.body.orderID,
                                "orderType": orderType,
                                "date": receiveDate,
                                "customerName": customerName,
                                "success": req.flash('success'),
                                "partNumber": partNumber,
                                "quantity": quantity,
                                "locationName": locationName,
                                "stageName": stageName

                            })

                            res.redirect('/orderDetails?' + query)

                        }

                    })
                    .catch(err => {
                        console.log(err)
                    })


            }

        })


        .catch(err => {
            console.log(err)
        })

父查询是我检索orderID的地方,并且遍历各种orderID来检索orderDetails并填充数组。但是,我很难让此代码在for循环内保持同步。

我希望console.log是:

here is 1
here is 2
here is 3

here is 1
here is 2 
here is 3

here is 1
here is 2 
here is 3 

相反,我得到了:

here is 1
here is 2
here is 1
here is 1
 here is 3
here is 2
here is 2
 here is 3
 here is 3

在这种情况下,每个异步代码正在执行正确的时间3,但是由于for循环,它根本不同步。有没有一种方法可以在循环内使用异步代码并使之同步?

2 个答案:

答案 0 :(得分:1)

for循环会立即进行所有迭代,从而进行所有顶级查询。

for循环结束时,在后台运行的异步DB请求与迭代次数一样多。

不能保证先解决所有迭代的承诺,然后再解决来自后续迭代的承诺。

简而言之,for循环不会等到所有承诺都得到解决。

解决方案-使用async/await

for (let i = 0; i < mainrow.length; i++) {

   await pool.query(foo);
   await pool.query(bar);
}

这是一种解决方法(也是首选)。

答案 1 :(得分:1)

这是您用async/await重写的代码。请记住,通过这种方法,您将一个接一个地执行每个请求,而不是像您对诺言那样并行执行。因此,此解决方案速度较慢。同样,如 zero298 指出的那样,您应该使用准备好的语句来避免SQL注入。

const partNumber = []
const stageName = []
const quantity = []
const locationName = []
let orderType, receiveDate, customerName
try {
  const mainrow = await pool.query(`select * from orderDetail where orderID = ${req.body.orderID} order by orderDetailID`)
  for (let i = 0; i < mainrow.length; i++) {
    quantity.push(mainrow[i].QtyShipped)
    let rows = await pool.query(`Select PartNumber from parts where partID = ${mainrow[i].PartID}`)
    console.log(`here is 1`)
    partNumber.push(rows[0].PartNumber)
    rows = await pool.query(`Select StageName from stages where StageID = ${mainrow[i].StageID}`)
    console.log(`here is 2`)
    rows = await pool.query(`Select LocationName from locations where locationID =${mainrow[i].LocationID}`)
    console.log(` here is 3`)
    locationName.push(rows[0].LocationName)
    stageName.push(rows[0].LocationName)
    orderType = mainrow[i].OrderType
    receiveDate = mainrow[0].receiveDate
    req.flash('success', `You returned back to the OrderID ${req.body.orderID}`)
    customerName = mainrow[0].CustomerName
  }
  const query = queryString.stringify({
    "orderID": req.body.orderID,
    "orderType": orderType,
    "date": receiveDate,
    "customerName": customerName,
    "success": req.flash('success'),
    "partNumber": partNumber,
    "quantity": quantity,
    "locationName": locationName,
    "stageName": stageName

  })
  res.redirect('/orderDetails?' + query)
} catch(err) {
  console.log(err)
}