Това е асинхронен проблем. Вие попълвате стойността на масива в обратно извикване. Но поради естеството на цикъла на събитията е невъзможно някое от обратните извиквания да бъде извикано до момента, в който console.log
се изпълнява.
Споменахте решение, включващо обещания, и това вероятно е правилният подход. Например нещо като следното:
exports = function(orgLoc_id, data) {
// ...
let stream_ids = [];
const promises = data.map(function(stream) {
return streamsCollection.findOne({ _id: stream.stream_id }, { type: 1, sizes: 1 })
.then(res => { //if I comment this query it will push without any problem
if (res) {
let newId = new BSON.ObjectId();
// ...
stream_ids.push(newId);
}
})
})
Promise.all(promises).then(function() {
console.log('stream ids: ' + stream_ids);
//TODO
// any code that needs access to stream_ids should be in here...
});
};
Обърнете внимание на промяната на forEach
към map
...по този начин получавате масив от всички Promises (предполагам, че вашият findOne
връща обещание поради .then
).
След това използвате Promise.all
да изчакате всички обещания да бъдат разрешени и тогава трябва да имате своя масив.
Странична бележка:По-елегантно решение би включвало връщане на newId
във вашия .then
. В този случай Promise.all
всъщност ще разреши с масив от резултатите на всички обещания, които биха били стойностите на newId
.