MongoDB和Node jsasynchronous编程

我正在尝试解决考试问题,所以无法发布我的考试代码。 所以我已经简化了,以至于说明了我不了解的核心概念。 基本上,我不知道如何减慢节点的asynchronous执行速度,这样我的mongo代码才能赶上它。 这里是代码:

MongoClient.connect('mongodb://localhost:27017/somedb', function(err, db) { if (err) throw err; var orphans = []; for (var i; i < 100000; i++) { var query = { 'images' : i }; db.collection('albums').findOne(query, function(err, doc_album) { if(err) throw err; if (doc_album === null) { orphans.push(i); } }); } console.dir(orphans.length); return db.close(); }); 

所以我想创build一个不符合我的查询条件的图像数组。 由于Node不会等待callback完成,所以最终得到的orphans.length值为0。 我怎样才能修改代码,使callback完成执行之前,我不符合我的查询条件数组中的图像数量?

在此先感谢您的时间。

巴拉特

我假设你想要做100000个并行数据库调用。 要在每个callbackcallback中“等待”10000个callback完成,我们增加完成的callback计数器,并在最后一个callback完成时调用主callback。 请注意,这里常见的错误是在callback中使用for循环variables作为闭包。 这并不像预期的那样工作,因为所有10000个处理程序首先被调度,并且首先被执行的循环variables是相同的最大值。

 function getOrphans(cb) { MongoClient.connect('mongodb://localhost:27017/somedb', function(err, db) { if (err) cb(err); var orphans = []; var numResponses = 0; var maxIndex = 100000 for (var i = 0; i < maxIndex; i++) { // problem: by the time you get reply "i" would be 100000. // closure variable changed to function argument: (function(index) { var query = { 'images' : index }; db.collection('albums').findOne(query, function(err, doc_album) { numResponses++; if(err) cb(err); if (doc_album === null) { orphans.push(index); } if (numResponses == maxIndex) { db.close(); cb(null, orphans); } }); })(i); // this is "immediately executed function } }); } getOrphans(function(err, o) { if (err) return console.log('error:', err); console.log(o.length); }); 

我不build议这是在Mongo中处理这个特定问题的最好方法,但是如果您需要等待数据库回复才能继续,那么只需使用callback启动下一个请求即可。

起初这不是很明显,但可以参考函数内部的结果处理函数:

 var i = 0; var mycback = function(err, doc_album) { // ... process i-th result ... if (++i < 100000) { db.collections("album").findOne({'images': i}, mycback); } else { // request is complete, "return" result result_cback(null, res); } }; db.collections('album').findOne({'images': 0}, mycback); 

这也意味着你的函数本身将是asynchronous的(即将需要一个result_cback参数调用的结果,而不是使用return )。

编写一个调用asynchronous的同步函数是不可能的。

您不能在Javascript中“等待”事件…您必须为结果设置处理程序,然后终止。

等待事件是通过编写一个“嵌套的事件循环”在基于事件的处理中完成的,例如在大多数GUI框架中如何处理消息框。 这是Javascriptdevise者不想给程序员的function(虽然不太清楚为什么)。

既然你知道它不等待电话回来。 你可以在你的callback函数中执行console.dir ,这应该可以工作(虽然我没有testing过)

  db.collection('albums').findOne(query, function(err, doc_album) { if(err) throw err; if (doc_album === null) { orphans.push(i); } console.dir(orphans.length); }); 

你不需要放慢速度。 如果您只是试图从相册集合中加载100,000张图片,则可以考虑使用asynchronous框架。 这将使您可以分配任务,直到作业完成。

另外,您可能不希望逐一请求100,000条logging。 相反,你可能想要分页。