项目用的nodejs来做 遇到一个问题求大神帮忙 查用户信息的时候因为要同时查询好几张表,所以就需要一次执行多个sql语句,这样就需要很多个嵌套函数了,还有最重要就是因为需要根据表中的每一条数据来查出相对应的数据,所以需要写出个循环来依次迭代查出的数据,并进行数据查询,实现方式 就是加了嵌套跟加了状态控制,功能虽然实现了,但是代码真是惨不忍睹!!贴出代码 dbService.psQuery(sql, [userId], function (rows) { user.userInfo = rows[0]; sql = sqls[‘user’][‘getUserPageShowList’][‘sql’]; dbService.psQuery(sql, [userId], function (rows) { user.playerList = rows; sql = sqls[‘user’][‘getUserPageActionList’][‘sql’]; /获取用户的动态信息/ dbService.psQuery(sql, [userId], function (rows) { sql = sqls[‘action’][‘getActionImgById’][‘sql’]; var lock = 0; for (var i = 0; i < rows.length; i++) { /根据动态信息来获取动态中的图集信息/ dbService.psQuery(sql, rows[i].ACTIONID, function (imgList) { if (imgList && imgList.length > 0) { rows[lock].imgList = imgList; } else { rows[lock].imgList = {}; } lock++; if (lock >= rows.length) { user.actionList = rows; /获取用户的图集信息/ sql = sqls[‘user’][‘getUserPageAlbumList’][‘sql’]; dbService.psQuery(sql, [userId], function (rows) { sql = sqls[‘album’][‘getAlbumImgById’][‘sql’]; var lock = 0; for (var i = 0; i < rows.length; i++) { dbService.psQuery(sql, rows[i].ALBUMID, function (imgList) { if (imgList && imgList.length > 0) { rows[lock].imgList = imgList; } else { rows[lock].imgList = {}; } lock++; if (lock >= rows.length) { user.albumList = rows; fn(user); } }); } });
}
});
}
});
});
});
小弟一直是做java开发的 刚学node 想想如果是同步执行的话的就简单多了吧 希望在大神们帮个忙能出个更好办法让这些代码解脱了啊
问题 nodejs mysql的查询就是事件驱动的
connection.query(sql, values, function (err, rows) {
if (err)throw err;
fn(rows);
});
有同步查询的么
@ngot 问题 nodejs mysql的查询就是事件驱动的 connection.query(sql, values, function (err, rows) { if (err)throw err; fn(rows); }); 有同步查询的么
async.waterfall([
function(callback){
dbService.psQuery(sql, [userId], callback);
},
function(rows, callback){
…
dbService.psQuery(sql, [userId], callback)
},
function(rows, callback){
…
dbService.psQuery(sql, [userId], callback);
},
function(rpws, callback){
async.forEach(rows, function(next){
async.waterfall([function(cb){
dbService.psQuery(sql, rows[i].ACTIONID,cb)
}, function(imageList, cb){
…
dbService.psQuery(sql, [userId], cb);
}, function(imageList, cb){
…
async.forEach(rows, function(next2){
dbService.psQuery(sql, rows[i].ALBUMID, function (imgList) {
…
next2();
});
},function(err){
cb();
})
}],function(err, results){
next();
});
}, function(err, results){
callback();
})
], function (err, result) { fn(user); });
@xinght 非常感谢 async.forEach(rows, function(next2){ dbService.psQuery(sql, rows[i].ALBUMID, function (imgList) { … next2(); }); next2(); 这个 函数是在循环到最后一次再执行呢 还是每次循环都会执行 想的的是 循环到最后一次再执行
@hainee 这些所有的sql耦合到一块了,那我有的地方要分开用一条独立的sql,是不是还要从新写一个,另外我取数据的时候,比如我查出所有表中前4个相册的记录,并且根据相册的id,来取出相片表中所有属于此相册的相片,数据结果应该是 {相册id:1000,图片信息:{图片1:1,图片2:2,图片3:3}} 如果用一条 sql我要怎么写 查出数据后我又该怎么取呢
@pensizhangtao 很简单,如果只是简单的一层主从关系,一张二维表就搞定了,举个很简单的例子: 1、tPhoto(相册):id, name 2、tPic(相片):id, tPhoto_id, name, pic_path 灰常简单的一句SQL: select tPic.id as PicId , tPic.tPhoto_id as PhotoId , tPic.name as pic_name as PicName , tPic.pic_path as PicPath ,tPhoto.name as PhotoName from tPic inner join tPhoto on tPic.tPhoto_id = tPhoto.id where tPhoto.id in(select top 4 id from tPhoto order by id desc);
这个查询结果序列化成JSON的格式是: //弄个变量存起来,后面给你做分组例子 var data = [ {PicId:1, PhotoId:1, PicName:"图片1", PicPath:"图片路径1", PhotoName:"相册1"} ,{PicId:2, PhotoId:1, PicName:"图片2", PicPath:"图片路径2", PhotoName:"相册1"} ,{PicId:3, PhotoId:1, PicName:"图片3", PicPath:"图片路径3", PhotoName:"相册1"}] //执行分组,写一个专门分组用的函数 function groupData(array, groupField) { var groupResult = {}; for (var i = 0; i < array.length; i++) { var data = array[i]; var groupValue = data[groupField]; var groupDataItem = groupResult[groupValue]; if(!groupDataItem) { groupResult[groupValue] = groupDataItem = []; groupDataItem[groupField] = groupValue; }; groupDataItem.push(data); }; return groupResult; };
var result = groupData(data, “PhotoId”);//这个result对象就是你说的{相册id:1000,图片信息:[图片1:1,图片2:2,图片3:3]},不过“图片信息”是数组对象,你可以自己修改分组函数,把这个对象改成Object,而不是Array 然后你就可以循环这个result对象来绘制你的UI了 这样处理你的数据比你在JS代码里面循环链接数据库再去查数据要快至少一个数量级:)
@pensizhangtao var rows = [1,2,3,4,5] async.forEach(rows, function(next){ //模拟异步处理 setTimeout(function(){ next();//本次异步处理结束后触发下次循环执行 },5000); },function(err){ //这个方法会在循环全部执行完后被调用 也就是你说的循环最后一次才执行的地方 });
@xinght 运行会报错哦 next 就是相当于 rows数据中的数字 ,所以会报 数字不是一个函数无法运行 的错误 对源码又看了下 试这改成下面这个 样子,成功打印了 不过,还是对其中原理有些模糊 var async = require(‘async’); var rows = [1, 2, 3, 4, 5] async.each(rows, function (row,next) { //模拟异步处理 console.log('1-' + row); next(); }, function (err) { //这个方法会在循环全部执行完后被调用 也就是你说的循环最后一次才执行的地方 console.log(‘2-1’); });
很感谢大家的帮助 @hainee 提的解决办法很对,不过这次我想好好掌握住nodejs的同步编程跟循环控制编程的技巧,现在问题已解决,贴出完整代码供大家分享,有不好的地方请大家指出(主要使用 async 来实现) var async = require(‘async’); exports.userInfo = function (userId, fn) {/信息/ var user = {userInfo: null, playerList: null, actionList: null, albumList: null}; var sql = null; async.series([function (callback) {/里面的函数信息通过 callback 依次执行/ sql = sqls[‘user’][‘getUserInfo’][‘sql’]; dbService.psQuery(sql, [userId], function (rows) { user.userInfo = rows[0]; callback(); }); }, function (callback) { sql = sqls[‘user’][‘getUserPageActionList’][‘sql’]; dbService.psQuery(sql, [userId], function (rows) { sql = sqls[‘action’][‘getActionImgById’][‘sql’]; user.actionList = rows; console.log(‘action.img.length:’ + rows.length); async.each(rows, function (row, last) {/last 函数为所有数据迭代完后 执行一次/ dbService.psQuery(sql, row.ACTIONID, function (imgList) { row.imgList = imgList; last(); }); }, function (err) {/迭代执行完毕/ callback(); }); }); }, function (callback) { sql = sqls[‘user’][‘getUserPageAlbumList’][‘sql’]; dbService.psQuery(sql, [userId], function (rows) { user.albumList = rows; sql = sqls[‘album’][‘getAlbumImgById’][‘sql’]; async.each(rows, function (row, last) {/last 函数为所有数据迭代完后 执行一次/ dbService.psQuery(sql, row.ALBUMID, function (imgList) { row.imgList = imgList; last(); }); }, function (err) { fn(user); }); }); }]); }