To kwestia asynchroniczna. Wypełniasz wartość tablicy wewnątrz wywołania zwrotnego. Jednak ze względu na naturę pętli zdarzeń niemożliwe jest, aby którykolwiek z wywołań zwrotnych został wywołany do czasu console.log
jest wykonywany.
Wspomniałeś o rozwiązaniu obejmującym obietnice i to jest prawdopodobnie właściwa taktyka. Na przykład coś takiego:
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...
});
};
Zwróć uwagę na zmianę forEach
do map
...w ten sposób otrzymujesz tablicę wszystkich obietnic (zakładam, że twoje findOne
zwraca obietnicę z powodu .then
).
Następnie używasz Promise.all
czekać na rozwiązanie wszystkich obietnic, a wtedy powinieneś mieć swoją tablicę.
Uwaga dodatkowa:bardziej eleganckie rozwiązanie wymagałoby zwrócenia newId
wewnątrz twojego .then
. W takim przypadku Promise.all
faktycznie rozwiąże się z tablicą wyników wszystkich obietnic, które będą wartościami newId
.