我使用nodejs通过Mongoose查询来自Mongodb的数据。 获取数据后,我想在响应客户端之前对该数据执行某些操作。但我无法获得回报价值。在Google上查看之后,我了解到Node.js函数是异步javascript函数(非I / O阻塞)。我尝试这个tut(http://www.youtube.com/watch?v=xDW9bK-9pNY),但它不起作用。以下是我的代码。 myObject在“find()”函数内部被赋值,在“find()”函数外部未定义。那么我该怎么做才能获得数据呢?谢谢!
var Person = mongoose.model('Person', PersonSchema);
var Product = mongoose.model('Product', ProductSchema);
var myObject = new Object();
Person.find().exec(function (err, docs) {
for (var i=0;i<docs.length;i++)
{
Product.find({ user: docs[i]._id},function (err, pers) {
myObject[i] = pers;
console.log(myObject[i]); //return the value is ok
});
console.log(myObject[i]); //return undefined value
}
console.log(myObject); //return undefined value
});
console.log(myObject); //return undefined value
app.listen(3000);
console.log('Listening on port 3000');
答案 0 :(得分:8)
您获取未定义值的原因是因为find函数是异步的,并且可以随时完成。在您的情况下,它在您使用console.log()
后完成,因此当您访问它们时,这些值是未定义的。
要解决此问题,您只能使用find函数回调中的值。它看起来像这样:
var Person = mongoose.model('Person', PersonSchema);
var Product = mongoose.model('Product', ProductSchema);
var myObject = new Object();
function getData(docs, callback) {
function loop(i) {
Product.find({ user: docs[i]._id}, function (err, pers) {
myObject[i] = pers;
if (i < docs.length) {
loop(i + 1);
} else {
callback();
}
});
};
loop(0);
};
Person.find().exec(function(err, docs) {
getData(docs, function() {
// myObject has been populated at this point
});
});
数据处理已移至循环,等待上一次迭代完成。这样,我们就可以确定最后一个回调被触发的时间,以便在包装函数中触发回调。
答案 1 :(得分:2)
请记住,在执行console.log函数时,查询尚未完成,因此将显示“undefined”。这就是nodeJS异步性的本质。
例如,
Person.find().exec(function (err, docs) {
for (var i=0;i<docs.length;i++)
{
Product.find({ user: docs[i]._id},function (err, pers) {
myObject[i] = pers;
console.log(myObject[i]); //return the value is ok
});
console.log(myObject[i]); //return undefined value
}
console.log(myObject); //return undefined value
});
console.log(myObject); // <-- Initially, this value will be undefined. After some miliseconds (Or the duration of the .exec function, myObject will contain the results.
如果你想要等到查询完成以便你可以使用这些值,我建议你将app.listen(3000);
和console.log('Listening on port 3000');
移到函数的最终回调中。
我还建议您查看this节点模块。它将帮助您更轻松地构建异步/同步函数,并允许您在完成所有异步函数时执行回调。