2013-09-23 140 views
2

我正在使用nodejs從MongoDB到Mongoose查詢數據。 獲取數據後,我希望在對客戶端進行響應之前對數據進行一些操作。但我無法獲得回報價值。在Google上查看之後,我瞭解到Node.js函數是異步JavaScript函數(非I/O阻塞)。我嘗試這個嘖嘖(http://www.youtube.com/watch?v=xDW9bK-9pNY),但它不工作。以下是我的代碼。 myObject在「find()」函數內部被賦值,而在「find()」函數外被undefined賦值。那麼我應該怎麼做才能獲得數據?謝謝!Nodejs中異步函數的返回值

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

這是我的帖子從github:https://github.com/LearnBoost/mongoose/issues/1706#issuecomment-24887415 –

回答

8

你得到未定義值的原因是因爲find函數是異步的,並且可以隨時完成。在你的情況下,在你使用console.log()後它會完成,所以當你訪問它們時,這些值是不確定的。

要解決此問題,只能使用查找函數回調中的值。它看起來像這樣:

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

數據處理已被移動到一個等待上一次迭代完成的循環。通過這種方式,我們可以確定最後一次回調何時觸發,以便在包裝函數中觸發回調。

+0

感謝hexacyanide,但它不工作,它不能讀取文檔的屬性[i] ._id –

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);console.log('Listening on port 3000');到函數的最終回調。

我還建議您查看this節點模塊。它將幫助您更輕鬆地構建異步/同步函數,並允許您在完成所有異步函數時執行回調。

+0

我看到這個「如果你只是想在全局範圍內設置/獲取值(在Person.find()。exec()...之外),但我可以在這裏看到它,是嗎? –