Javascript MongoDB和Node js异步编程
我正试图解决一道考试题,所以我不能按原样发布考试代码。因此,我对其进行了简化,以解决我不理解的核心概念。基本上,我不知道如何降低节点的异步执行速度,以便我的mongo代码能够赶上它。代码如下: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++)
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;ifunction 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);
});