刚接触nodejs不久,最近使用express框架做一个api平台。使用了Mysql数据库。然而,在MYSQL查询的时候,遇到了一个问题解决不了。
要实现的功能: 查询项目列表信息(project表),并且同时返回用户的昵称,头像(user表)。
问题描述: 要返回的总数组为datas。在第一次SQL查询中,成功获得了project表的所有信息,然后,遍历每一条记录,并且获取每一条记录所属的用户ID,第二次SQL查询则是根据用户ID来获取nickname和avatar。然后合并。最后返回。
但是现在出现问题:返回的结果,只是第一次查询的内容数组。第二次的没有合并成功。 虽然通过联合查询可以实现该功能,但是在其他地方还是遇到了这个问题,并且没法使用联合查询。所以迫切的需要解决该问题。
============================================= project表: id user_id title content
user表: id nickname avatar
我最先开始是使用了2个select语句来实现。但是无法把user表的信息组合到总信息数组中。代码如下: exports.recommendList = function(req, res){ res.setHeader(‘Content-Type’, ‘application/json;charset=utf-8’); res.setHeader(‘Access-Control-Allow-Origin’, '’); var user_id =’’; var page = parseInt(req.params.page); var pagesize = 3; var offset = pagesize(page-1); var sql = “select * from project where status!=0 and recommend =1 order by id desc limit “+offset+”,”+pagesize;
conn.query(sql,function(err,rows){
if (err) {
console.log(err);
}else{
var i = 0;
var datas = new Array();
rows.forEach(function(row){
var user_id = row.user_id;
var user_sql = "select avatar,nickname from user where id="+user_id;
conn.query(user_sql,function(err,result){
if (err) {
console.log(err);
}else{
var nickname = result[0].nickname;
var avatar = result[0].avatar;
console.log("nickname="+nickname);
console.log("avatar="+avatar);
row.nickname = nickname;
row.avatar = avatar;
console.log(row); //这里合并成功
}
})
datas[i]=row; //这里不显示合并后的结果。只显示第一次查询后的结果
i++;
})
console.log(datas);
res.json({code: 200,content:datas})
}
});
};
请使用async库或promise等异步流程处理库
来自酷炫的 CNodeMD
@o6875461 这方面的资料好少。搜索async,很多结果都只是一个async.eachSeries的示例例子,可以顺序执行。但是返回值怎么弄呢
async呢,你可以这样用
//存储查询的sql语句的数组
let sqlArr = [];
//存储查询结果的对象
let resObj = {};
async.eachSeries(sqlArr, function(item, callback){
db.query(item, function(err, rows){
if(err){
return callback(err);
}
resObj[item] = rows;
callback(null);
}));
},function(err) {
if(err){
return console.error(err)
}
//对结果进行处理...结果均在resObj中,key为sql语句,value为语句对应的sql执行结果
console.log(resObj);
});
接楼上,但是async库在现在co和promise都存在的情况下,意义已经没有那么大了,你也可以发现,上面的代码虽说解决了一定的cb嵌套,但是还是很难看,下面是promise的写法
//首先你要把db.query封装成一个promise,如下:
//这部分代码你可以放到公共lib文件里面
function query(sql){
return new Promise(function (resolve, reject){
db.query(sql, function(err, rows){
if(err)
return reject(err);
relsolve(rows);
});
});
}
//下面是主逻辑
//存储查询的sql语句的数组
let sqlArr = [];
//构造一个promiseArr存储所有的db查询promise对象
let promiseArr =sqlArr.map(item=>query(item));
//使用Promise.all方法执行;then中的dataArr即为查询的结果,顺序和sqlArr中的sql一致,处理逻辑可以放在这里;最后的catch是异常捕获,异常处理放在这里
Promise.all(promiseArr).then(dataArr=>console.log(dataArr)).catch(err=>console.error(err));
两表联查不行吗?这种问题不应该在node里面处理。 select * from project p left join user u on p.userid = u.userid;