nodejs:在for循环中保存函数,asynchronous问题

NodeJS + Express,MongoDB + Mongoose

我有一个JSON feed,每个logging都有一组“场地”属性(比如“场地名称”,“场地位置”,“场地电话”等等)。 我想创build一个饲料中的所有场地的集合 – 每个场地的一个例子,没有愚蠢。

我通过JSON循环testing场地是否存在于场馆中。 如果没有,保存。

jsonObj.events.forEach(function(element, index, array){ Venue.findOne({'name': element.vname}, function(err,doc){ if(doc == null){ var instance = new Venue(); instance.name = element.vname; instance.location = element.location; instance.phone = element.vphone; instance.save(); } } } 

期望:所有场地的列表(没有模糊)。

结果:在场馆收集了大量的骗局。

基本上,循环为JSON提要中的每个logging创build了一个新的Venuelogging。

我正在学习Node及其asynchronous特性,所以我相信即使在第一个save()函数完成之前,for循环也会完成 – 所以if语句总是检查一个空集合。 Console.logging支持这个声明。

我不知道如何重做,以便它执行所需的任务。 我试过caolan的asynchronous模块,但是我无法得到它的帮助。 有一个很好的机会我使用不当。

非常感谢你指点我正确的方向 – 我已经无济于事了。 如果asynchronous模块是正确的答案,我想在这个特定情况下如何实现它的帮助。

再次感谢!

为什么不用另一种方式呢? 你没有说什么你的持久层,但看起来像mongoose或可能FastLegS。 无论哪种情况,您都可以在名称字段上创build唯一索引。 然后,您可以尝试保存任何内容,并在出现唯一索引违规时处理该错误。

无论你做什么,你都必须像@Paulbuild议的那样做,并在数据库中build立一个唯一的索引。 这是确保唯一性的唯一方法。

但是,你的代码的主要问题是,在instance.save()调用中,你需要一个callback,触发下一个迭代,否则数据库将没有时间来保存新的logging。 这是一个竞争条件。 你可以用caolan的forEachSeries函数来解决这个问题。

或者,您可以在Venue集合中获取与JSON对象中项目匹配的logging数组,然后将匹配项过滤出对象,然后迭代添加已过滤JSON对象中剩下的每个项目。 这将通过不首先创build重复数据库来最大限度地减less数据库操作的数量。

 Venue.find({'name': { $in: jsonObj.events.map(function(event){ return event.vname; }) }}, function (err, docs){ var existingVnames = docs.map(function(doc){ return doc.name; }); var filteredEvents = jsonObj.events.filter(function(event){ return existingVnames.indexOf(event.vname) === -1; }); filteredEvents.forEach(function(event){ var venue = new Venue(); venue.name = event.vname; venue.location = event.location; venue.phone = event.vphone; venue.save(function (err){ // Optionally, do some logging here, perhaps. if (err) return console.error('Something went wrong!'); else return console.log('Successfully created new venue %s', venue.name); }); }); });