需求:
嵌套查询,当完成第一次对数据库的查询后,想要对另一个表再进行查询,且需要用到第一次查询的结果,该结果为对象数组。
对另一个表进行查询时,是根据该对象数组中每个元素的其中一个属性来查询的,而且对 对象数组 的每次循环都要改变数组元素(即为每个元素增加一个新的属性)。
错误写法:(省略号就是省略了一些不重要的代码)
exports.xxx = (req, res) => {
...
const sql = `select * from xxx1 where id=? `
db.query(sql, [id], (err, results) => {
// 执行 SQL 语句失败
if (err) return ...
// SQL 语句执行成功
if (results.length > 0) {
const sql2= `select * from xxx2 where cid=? and id=?`
for (...) {
db.query(sql2, [results[i].cid, id], function (err, results2) {
// 执行 SQL 语句失败
if (err) return ...
// SQL 语句执行成功
if (results2.length === 1) {
results[i]= Object.assign(results[i], {
liked: true
});
} else {
results[i]= Object.assign(results[i], {
liked: false
});
}
});
}
res.send({
status: 200,
message: '成功',
data: results,
})
} else {
res.send({
status: 200,
message: '暂无',
data: []
})
}
})
}
我本意是想让循环结束以后,再send数据回前端的,但是因为代码执行顺序,导致 res.send先执行了,即前端收到的是未处理的第一次查数据库的结果。
解决方法:(async第三方模块,标红的就是重点)
//导入async模块(记得要先npm install async)
const async = require('async');
......
exports.xxx = (req, res) => {
...
const sql = `select * from xxx1 where id=? `
db.query(sql, [id], (err, results) => {
// 执行 SQL 语句失败
if (err) return ...
// SQL 语句执行成功
if (results.length > 0) {
const sql2= `select * from xxx2 where cid=? and id=?`
//这里 async.forEachOf的第一个参数就是要循环的数组,剩下的应该看得懂
async.forEachOf(results, function (item, i, callback) {
db.query(sql2, [item.cid, id], function (err, results2) {
// 执行 SQL 语句失败
if (err) return ...
// SQL 语句执行成功
if (results2.length === 1) {
item = Object.assign(item, {
liked: true
});
} else {
item = Object.assign(item, {
liked: false
});
}
callback();
});
}, function (err) {
if (err) {
//handle the error if the query throws an error
return ...
} else {
//whatever you wanna do after all the iterations are done
res.send({
status: 200,
message: '成功',
data: results,
})
}
});
} else {
res.send({
status: 200,
message: '暂无',
data: []
})
}
})
}