节点js中的循环同步

时间:2015-07-17 21:34:48

标签: node.js mongodb asynchronous promise synchronous

所以,让我说我有以下循环

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次。在继续下一次迭代之前,如何解决此问题并等待查询完成?

3 个答案:

答案 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
            }
        }
    }
}