节点js中的同步for循环

Synchronous for loop in node js

假设我有以下 for 循环

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 次。我该如何着手解决这个问题并等待查询完成才能继续下一次迭代?

完成您想要的事情的最简单方法之一是使用承诺。您可以使用库 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 */ });

这不是最漂亮的实现,但我相信你明白了:)

这并没有具体回答您的问题,而是解决了您的问题。

我会使用 $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
});

不确定这是否正确,它可能有点贵,但我是这样做的。 我认为诀窍是提取所有数据,然后寻找 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
            }
        }
    }
}