javascript Nodejs中异步函数的返回值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18950984/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
return value from asynchronous function in Nodejs
提问by Vo Thanh Thang
I am using nodejs to query data from Mongodb throught Mongoose. After get the data, I want do something on that data before responding it to client. But I can not get the return-value. After looking on Google, I have learned Node.js functions is asynchronous javascript function (non I/O blocking). I try this tut (http://www.youtube.com/watch?v=xDW9bK-9pNY) but it is not work. Below is my code. The myObject is valued inside "find()" function and undefined outside "find()" function. So what should I do to get the data? Thanks!
我正在使用 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');
回答by hexacyanide
The reason you're getting undefined values is because the find function is asynchronous, and can finish at any time. In your case, it is finishing after you're using console.log()
, so the values are undefined when you're accessing them.
您获得未定义值的原因是 find 函数是异步的,并且可以随时完成。在您的情况下,它在您使用后完成console.log()
,因此在您访问它们时这些值是未定义的。
To fix this problem, you can only use the values inside the find function's callback. It would look something like this:
要解决此问题,您只能使用 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
});
});
The data processing has been moved to a loop that waits for the previous iteration to complete. This way, we can determine when the last callback has fired in order to fire the callback in the wrapper function.
数据处理已转移到等待前一次迭代完成的循环中。通过这种方式,我们可以确定上次回调何时触发,以便在包装函数中触发回调。
回答by David Oliveros
Keep in mind that by the time the console.log functions are executed, the query has not yet finished, thus will display "undefined". That's the essence of nodeJS's asynchronicity.
请记住,在执行 console.log 函数时,查询尚未完成,因此将显示“未定义”。这就是 nodeJS 异步性的本质。
For example,
例如,
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.
If you want to actually wait until the query is finished so you can use the values, I would recommend moving the app.listen(3000);
and console.log('Listening on port 3000');
into the function's final callback.
如果您想真正等到查询完成以便您可以使用这些值,我建议将app.listen(3000);
和移动console.log('Listening on port 3000');
到函数的最终回调中。
I'd also recommend you to check out thisnode module. It will help you build asynchronous / synchronous functions more easily, and allow you to execute a callback when all the asynchronous functions are finished.
我还建议您查看此节点模块。它将帮助您更轻松地构建异步/同步函数,并允许您在所有异步函数完成后执行回调。