Javascript MongoDB和Node js异步编程

Javascript MongoDB和Node js异步编程,javascript,node.js,mongodb,asynchronous,Javascript,Node.js,Mongodb,Asynchronous,我正试图解决一道考试题,所以我不能按原样发布考试代码。因此,我对其进行了简化,以解决我不理解的核心概念。基本上,我不知道如何降低节点的异步执行速度,以便我的mongo代码能够赶上它。代码如下: MongoClient.connect('mongodb://localhost:27017/somedb', function(err, db) { if (err) throw err; var orphans = []; for (var i; i < 100000; i++)

我正试图解决一道考试题,所以我不能按原样发布考试代码。因此,我对其进行了简化,以解决我不理解的核心概念。基本上,我不知道如何降低节点的异步执行速度,以便我的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();
});
MongoClient.connect('mongodb://localhost:27017/somedb,函数(err,db){
如果(错误)抛出错误;
var=[];
对于(变量i;i<100000;i++){
var query={'images':i};
db.collection('albums').findOne(查询、函数(err、doc\u相册){
如果(错误)抛出错误;
if(doc_相册===null){
孤儿。推(i);
}
});
}
console.dir(孤立项长度);
返回db.close();
});
因此,我试图创建一个与我的查询条件不匹配的图像数组。由于节点不等待回调完成,因此我的最终值为0.length。如何修改代码,使回调在计算数组中不符合查询条件的图像数之前完成执行

提前感谢您抽出时间


Bharat

因为您知道它不会等待呼叫返回。您可以在回调函数中执行
console.dir
,这应该可以工作(尽管我还没有测试它)


你不需要放慢速度。如果您只是试图从相册集合加载100000个图像,可以考虑使用框架。这将允许您分配任务,直到作业完成


此外,您可能不希望逐个请求100000条记录。相反,您可能希望对其进行分页。

我并不是建议这是处理Mongo中此特定问题的最佳方法,但如果您需要等待DB回复后再继续,则只需使用回调来启动下一个请求

这一点一开始并不明显,但您可以参考函数本身中的结果处理函数:

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);
var i=0;
var mycback=函数(错误,文档相册){
//…处理第i个结果。。。
如果(++i<100000){
db.collections(“album”).findOne({'images':i},mycback);
}否则{
//请求已完成,“返回”结果
结果返回(空,res);
}
};
db.collections('album').findOne({'images':0},mycback);
这也意味着您的函数本身将是异步的(即希望使用
result\u cback
参数调用结果,而不是使用
return

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

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


等待事件是通过编写“嵌套事件循环”在基于事件的处理中完成的,这就是大多数GUI框架中处理消息框的方式。这是Javascript设计人员不想给程序员的一种功能(但不知道为什么)。

我假设您想进行100000次并行DB调用。为了在每个调用回调中“等待”10000个调用完成,我们增加finished calls计数器,并在最后一个调用完成时调用main callback。请注意,这里最常见的错误是将for循环变量用作回调内的闭包。这并不像预期的那样工作,因为所有10000个首先调度的处理程序,并且在第一次执行时,循环变量的最大值相同

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);
 });
函数getOlivers(cb){ MongoClient.connect('mongodb://localhost:27017/somedb,函数(err,db){ 如果(错误)cb(错误); var=[]; var numResponses=0; var maxIndex=100000 对于(变量i=0;i
'images':{$in:[…]}
这是有效的。谢谢。问题:这之所以有效,是因为您在上面的评论部分中显示了“立即执行的函数”?请您进一步详细说明一下。使用新的
let
,是否可以更容易/更直观地解决这个问题,如(设i=0;i
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);
 });