这一节是对上一篇文件的知识扩展,扩展点在异步查询数据库。
上面在获取show页面内容时,我查询了两个表,第一次查询question,然后用获取的name属性,继续遍历查询user表中图片地址。
大家看看我下面的代码有没有问题:
mongodb.open(function(err, db){
if(err){
return callback(err);
}
//读取 users 集合
db.collection('question', function(err, collection){
if(err){
mongodb.close();
return callback(err);
}
//查找用户名 name 值为 name文档
collection.find({hide:{$ne:false}}).limit(5).sort({time:-1}).toArray(function(err,items){
if(err) throw err;
//二次查询
db.collection('info', function(err, collection){
var newData=[];
for(var i=0,l=items.length;i<l;i++){
collection.find({name:items[i].name}).toArray(function(err,itens){
newData.push(itens);
});
}
});
mongodb.close();
//返回遍历数据
return callback(newData);
});
});
});
大家可以试试,上面的无法进行二次查询的。原理就是node的异步原理,我当时认为的流程是,每查询一次,push一次结果,然后下一次查询,最后完成for循环,关闭数据库,返回数据。
但是真实的情况是,开始三次查询,然后关闭数据库,没有返回数据这个步骤
下面将代码展开,假设二次查询的for循环两次:
1 collection.findOne({name: items[0].name},function(err, doc){
3 items[0].imgUrl=doc.imgUrl;
open++;
if(open==l){
mongodb.close();
return callback(items);
}
});
2 collection.findOne({name: items[1].name},function(err, doc){
4 items[1].imgUrl=doc.imgUrl;
open++;
if(open==l){
mongodb.close();
return callback(items);
}
});
上面绿色数字是我断点的js执行次序,可以发现查询数据库是一个一步过程,不是同步的,想要同步就只能回调处理,我在上一节的处理方法是保持异步,但是判断是否都返回,都返回才关闭数据库。将关闭数据了放在回调中。