从Nodejs中的异步函数返回值

时间:2013-09-23 02:33:33

标签: javascript node.js asynchronous mongoose return-value

我使用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');

2 个答案:

答案 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节点模块。它将帮助您更轻松地构建异步/同步函数,并允许您在完成所有异步函数时执行回调。