Det er et asynkront problem. Du udfylder værdien af arrayet i et tilbagekald. Men på grund af begivenhedsløkkens karakter er det umuligt, at nogen af tilbagekaldene vil være blevet kaldt på det tidspunkt, console.log
udføres.
Du nævnte en løsning, der involverer løfter, og det er nok den rigtige vej. For eksempel noget i stil med følgende:
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...
});
};
Bemærk ændringen af forEach
at map
...på den måde får du en række af alle løfterne (jeg går ud fra din findOne
returnerer et løfte på grund af .then
).
Så bruger du en Promise.all
at vente på, at alle løfterne løser sig, og så skulle du have dit array.
Sidebemærkning:En mere elegant løsning ville involvere returnering af newId
inde i din .then
. I så fald Promise.all
vil faktisk løses med en række af resultaterne af alle løfterne, som ville være værdierne af newId
.