2

私は nodejs を使用して、Mongodb から Mongoose 経由でデータをクエリしています。データを取得した後、クライアントに応答する前にそのデータに対して何かをしたいです。しかし、戻り値を取得できません。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');
4

2 に答える 2

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
  });
});

データ処理は、前の繰り返しが完了するのを待つループに移動されました。このようにして、ラッパー関数でコールバックを起動するために、最後のコールバックがいつ起動したかを判断できます。

于 2013-09-23T03:04:28.760 に答える
2

console.log 関数が実行されるまでには、クエリはまだ終了していないため、「未定義」と表示されることに注意してください。これが 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);andconsole.log('Listening on port 3000');を関数の最終コールバックに移動することをお勧めします。

また、このnode モジュールを確認することをお勧めします。非同期/同期関数をより簡単に構築するのに役立ち、すべての非同期関数が終了したときにコールバックを実行できます。

于 2013-09-23T03:10:31.913 に答える