É um problema assíncrono. Você está preenchendo o valor da matriz dentro de um retorno de chamada. Mas devido à natureza do loop de eventos, é impossível que qualquer um dos retornos de chamada tenha sido chamado no momento em que o
console.log
É executado. Você mencionou uma solução envolvendo promessas, e essa é provavelmente a tática certa. Por exemplo algo como o seguinte:
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...
});
};
Observe a mudança de
forEach
para map
...dessa forma você está obtendo uma matriz de todas as Promessas (estou assumindo que seu findOne
está retornando uma promessa por causa do .then
). Então você usa um
Promise.all
para esperar que todas as promessas sejam resolvidas, e então você deve ter seu array. Nota lateral:uma solução mais elegante envolveria retornar
newId
dentro do seu .then
. Nesse caso Promise.all
irá realmente resolver com uma matriz dos resultados de todas as promessas, que seriam os valores de newId
.