在查询无法正常工作的情况下推入 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...
  });
};

注意 forEachmap 的变化......这样你就得到了所有承诺的数组(我假设你的 findOne 正在返回一个承诺因为 .then).

然后你使用 Promise.all 等待所有的承诺解决,然后你应该有你的数组。

旁注:一个更优雅的解决方案是在 .then 中返回 newId。在那种情况下 Promise.all 实际上会解析所有承诺的结果数组,这将是 newId.

的值