在查询无法正常工作的情况下推入 forEach
Push inside forEach with query not working properly
我正在使用 mongodb stitch/realm,我正在尝试使用 foreach 修改数组中的对象,并将 id 推入新数组。
对于我正在修改的每个对象,我也首先进行查询,在找到文档后我开始修改对象,然后将 id 推入另一个数组,以便稍后可以使用这两个数组。
代码是这样的:
exports = function(orgLoc_id, data){
var HttpStatus = require('http-status-codes');
// Access DB
const db_name = context.values.get("database").name;
const db = context.services.get("mongodb-atlas").db(db_name);
const orgLocPickupPointCollection = db.collection("organizations.pickup_points");
const orgLocStreamsCollection = db.collection("organizations.streams");
const streamsCollection = db.collection("streams");
let stream_ids = [];
data.forEach(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._id = newId;
stream.location_id = orgLoc_id;
stream.stream_type = res.type;
stream.unit_price = res.sizes[0].unit_price_dropoff;
stream._created = new Date();
stream._modified = new Date();
stream._active = true;
stream_ids.push(newId);
}
})
})
console.log('stream ids: ' + stream_ids);
//TODO
};
但是当我尝试记录 'stream_ids' 时,它是空的,没有任何显示。未分配属性 stream_type 和 unit_price。
我尝试过 promises 但我没有成功
这是一个异步问题。您正在回调中填充数组的值。但是由于事件循环的性质,不可能在 console.log
执行时调用任何回调。
您提到了一个涉及承诺的解决方案,这可能是正确的方法。例如像下面这样的东西:
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...
});
};
注意 forEach
到 map
的变化......这样你就得到了所有承诺的数组(我假设你的 findOne
正在返回一个承诺因为 .then
).
然后你使用 Promise.all
等待所有的承诺解决,然后你应该有你的数组。
旁注:一个更优雅的解决方案是在 .then
中返回 newId
。在那种情况下 Promise.all
实际上会解析所有承诺的结果数组,这将是 newId
.
的值
我正在使用 mongodb stitch/realm,我正在尝试使用 foreach 修改数组中的对象,并将 id 推入新数组。
对于我正在修改的每个对象,我也首先进行查询,在找到文档后我开始修改对象,然后将 id 推入另一个数组,以便稍后可以使用这两个数组。
代码是这样的:
exports = function(orgLoc_id, data){
var HttpStatus = require('http-status-codes');
// Access DB
const db_name = context.values.get("database").name;
const db = context.services.get("mongodb-atlas").db(db_name);
const orgLocPickupPointCollection = db.collection("organizations.pickup_points");
const orgLocStreamsCollection = db.collection("organizations.streams");
const streamsCollection = db.collection("streams");
let stream_ids = [];
data.forEach(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._id = newId;
stream.location_id = orgLoc_id;
stream.stream_type = res.type;
stream.unit_price = res.sizes[0].unit_price_dropoff;
stream._created = new Date();
stream._modified = new Date();
stream._active = true;
stream_ids.push(newId);
}
})
})
console.log('stream ids: ' + stream_ids);
//TODO
};
但是当我尝试记录 'stream_ids' 时,它是空的,没有任何显示。未分配属性 stream_type 和 unit_price。
我尝试过 promises 但我没有成功
这是一个异步问题。您正在回调中填充数组的值。但是由于事件循环的性质,不可能在 console.log
执行时调用任何回调。
您提到了一个涉及承诺的解决方案,这可能是正确的方法。例如像下面这样的东西:
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...
});
};
注意 forEach
到 map
的变化......这样你就得到了所有承诺的数组(我假设你的 findOne
正在返回一个承诺因为 .then
).
然后你使用 Promise.all
等待所有的承诺解决,然后你应该有你的数组。
旁注:一个更优雅的解决方案是在 .then
中返回 newId
。在那种情况下 Promise.all
实际上会解析所有承诺的结果数组,这将是 newId
.