Đó là một vấn đề không đồng bộ. Bạn đang điền giá trị của mảng vào bên trong một lệnh gọi lại. Nhưng do bản chất của vòng lặp sự kiện, không thể có bất kỳ lệnh gọi lại nào được gọi vào thời điểm console.log
được thực thi.
Bạn đã đề cập đến một giải pháp liên quan đến lời hứa, và đó có lẽ là giải pháp phù hợp. Ví dụ một cái gì đó như sau:
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...
});
};
Lưu ý sự thay đổi của forEach
tới map
... theo cách đó, bạn sẽ nhận được một loạt tất cả các Lời hứa (Tôi giả sử là findOne
của bạn đang trả về một lời hứa vì .then
).
Sau đó, bạn sử dụng Promise.all
đợi tất cả các lời hứa giải quyết và sau đó bạn sẽ có mảng của mình.
Lưu ý bên:Một giải pháp thanh lịch hơn sẽ liên quan đến việc trả lại newId
bên trong .then
của bạn . Trong trường hợp đó, Promise.all
sẽ thực sự giải quyết bằng một mảng kết quả của tất cả các lời hứa, sẽ là các giá trị của newId
.