我的数据库中有两个产品系列和库存。每个产品都有多种产品,产品的供应商和属性不同。 我从产品系列中选择了产品并为每个产品运行一个循环。我需要将库存集中的价格和报价附加到我已经选择的产品上。 我认为for循环在执行库存集合上的find方法之前完成了它的执行。我需要以串行方式执行循环中的所有内容(非异步)。请检查下面的代码并帮我解决这个问题。我是node.js和mongodb的新手
collection = db.collection('products');
collection.find().toArray(function(err, abc) {
var finalout = [];
for( var listProducts in abc){
var subfinal = {
'_id' :abc[listProducts]['_id'],
'min_price' :abc[listProducts]['value']['price'],
'stock' :abc[listProducts]['value']['stock'],
'name' :abc[listProducts]['value']['name'],
'price' :'',
'offer_price' :'',
};
collection = db.collection('stock');
collection.find({"product":abc[listProducts]['_id'] ,"supplier":abc[listProducts]['value']['def_supplier']}).toArray(function(err, newprod) {
for( var row in newprod){
subfinal['price'] = newprod[row]['price'];
subfinal.offer_price = newprod[row]['offer_price'];
}
finalout.push(subfinal);
});
}
console.log(finalout);
});
答案 0 :(得分:0)
是的,循环正在运行并同时在数据库上启动get请求。像你说的那样,有可能按顺序运行它们,但它可能不是你想要的。这样做会花费更多的时间,因为对Mongo的每个请求都需要等待前一个请求完成。
考虑到循环的每次迭代都不依赖于之前的迭代,所有你真正想要的是一旦所有操作都完成就知道了。请记住,这些可以以任何顺序结束,不一定是它们在循环中启动的顺序。
创建subfinal
变量时也存在问题。由于所有迭代都使用相同的变量名称,当它们全部返回时,它们将使用变量的最终赋值(所有结果将写在同一subfinal
上,这将被多次推送进入结果)。为了解决这个问题,我将整个项目处理迭代包装到另一个函数中,为每个subfinal
变量赋予它自己的范围。
有plenty of modules来简化这种管理,但是这里只有在使用不需要任何额外安装的计数器和回调完成所有Mongo调用之后运行某些代码的方法之一:
var finished = 0; // incremented every time an iteration is done
var total = Object.keys(abc).length; // number of keys in the hash table
collection = db.collection('products');
collection.find().toArray(function(err, abc) {
var finalout = [];
for( var listProducts in abc){
processItem(listProducts);
}
});
function processItem(listProducts) {
var subfinal = {
'_id' :abc[listProducts]['_id'],
'min_price' :abc[listProducts]['value']['price'],
'stock' :abc[listProducts]['value']['stock'],
'name' :abc[listProducts]['value']['name'],
'price' :'',
'offer_price' :'',
};
collection = db.collection('stock');
collection.find({"product":abc[listProducts]['_id'] ,"supplier":abc[listProducts]['value']['def_supplier']}).toArray(function(err, newprod) {
for( var row in newprod){
subfinal['price'] = newprod[row]['price'];
subfinal.offer_price = newprod[row]['offer_price'];
}
finalout.push(subfinal);
finished++;
if (finished === total) { // if this is the last one to finish.
allFinished(finalout);
}
});
}
function allFinished(finalout) {
console.log(finalout);
}
可以用更少的变量更简洁地编写,但这样更容易理解。