所以,让我说我有以下循环
for(var i = 0; i < array.length; i++){
Model.findOne({ _id = array[i].id}, function(err, found){
//Some stuff
});
}
如何使此代码生效?每次运行它都会得到array[i] = undefined
,因为mongo-db查询是异步的,并且循环在第一个查询完成时已经迭代了5次。在继续下一次迭代之前,如何解决此问题并等待查询完成?
答案 0 :(得分:1)
这并不是专门回答您的问题,而是解决您的问题。
我使用$ in查询并立即进行过滤。与1:
相比,对数据库的20次调用相当慢// grab your ids
var arrayIds = myArray.map(function(item) {
return item._id;
});
// find all of them
Model.find({_id: {$in: arrayIds}}, function(error, foundItems) {
if (error) {
// error handle
}
// set up a map of the found ids
var foundItemsMap = {};
foundItems.forEach(function(item) {
foundItemsMap[item._id] = true;
});
// pull out your items that haven't been created yet
var newItems = [];
for (var i = 0; i < myArray.length; i++) {
var arrayItem = myArray[i];
if ( foundItemsMap[arrayItem._id] ) {
// this array item exists in the map of foundIds
// so the item already exists in the database
}
else {
// it doesn't exist, push it into the new array
newItems.push(arrayItem);
}
}
// now you have `newItems`, an array of objects that aren't in the database
});
答案 1 :(得分:0)
实现类似事情的最简单方法之一就是使用承诺。您可以使用库q
执行此操作:
var Q = require('q');
function fetchOne(id) {
var deferred = Q.defer();
Model.findOne({ _id = id}, function(err, found){
if(err) deferred.reject(err);
else deferred.resolve(found);
});
return deferred.promise;
}
function fetch(ids, action) {
if(ids.length === 0) return;
var id = ids.pop();
fetchOne(id).then(function(model) {
action(model);
fetch(ids, action);
});
}
fetch([1,2,3,4,5], function(model) { /* do something */ });
这不是最美丽的实现,但我相信你能得到图片:)
答案 2 :(得分:0)
不确定这是否是正确的方法,它可能有点贵但是我这样做了。 我认为诀窍是提取所有数据然后寻找id匹配。
Model.find(function(err, data) {
if (err) //handle it
for (var i=0; i<array.length; i++) {
for (var j=0; ij<data.length; j++) {
if(data[j].id == array[i].id) {
// do something
}
}
}
}