我试图使用承诺的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循环,它根本不同步。有没有一种方法可以在循环内使用异步代码并使之同步?
答案 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)
}