Det är ett asynkront problem. Du fyller i värdet på arrayen i en återuppringning. Men på grund av händelseslingans natur är det omöjligt att någon av återuppringningarna kommer att ha anropats vid tidpunkten för console.log
exekveras.
Du nämnde en lösning som involverar löften, och det är förmodligen den rätta vägen. Till exempel något i stil med följande:
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...
});
};
Notera ändringen av forEach
för att map
...på så sätt får du en mängd alla löften (jag antar att din findOne
returnerar ett löfte på grund av .then
).
Sedan använder du en Promise.all
att vänta på att alla löften ska lösa sig, och sedan bör du ha din array.
Sidanteckning:En mer elegant lösning skulle innebära att returnera newId
inuti din .then
. I så fall Promise.all
kommer faktiskt att lösas med en uppsättning av resultaten av alla löften, vilket skulle vara värdena för newId
.