节点js中嵌套的异步mongoDB调用

时间:2016-08-19 15:19:47

标签: node.js mongodb asynchronous callback

我有一个非常简单的问题,但我无法找到解决此问题的优雅解决方案。 在下面的代码中,我有两个嵌套调用mongo DB。我用Monk管理我的电话。 问题是:在嵌套插入发生之前,for循环(1)循环。所以下一个find(2)指令找不到最后插入的动作。

呼叫顺序是1-2-2-2-3-3-3(对于大小为3的actionList)。所以我插入了所有数据。

我的目标是拨打电话1-2-3-2-3-2-3

您是否有任何关于如何管理此类问题的线索,而无需在我的数据库上进行大量查找并管理我的列表服务器端? (获取所有数据,使自己成为搜索,这是非常可怕的,插入我想要的元素,然后将其全部推送到数据库...)

for (var action of actionList)//(1)
{
    collectionActions.find(//(2)
        {eventid : action.eventid}, 
        function(e,actionsFound)
        {
            if (actionsFound.length == 0)
            {
                collectionActions.insert(action, function(err, result)//(3)
                {
                    console.log("insert action : " + action._id);
                })
            }
        }
    )
}

2 个答案:

答案 0 :(得分:2)

原生Promise对象有all方法,可以利用它来提供帮助。

假设find是一个合规的承诺,以下代码将通过map排队数组中的所有操作,并为最终返回消息的每个action返回一个承诺到then的最终all

一些注意事项:您的代码会吞下可能发生的所有错误(我不确定您是否想要这样);这也假设insert返回一个承诺。

Promise.all([
  // Iterate over actionList
  actionList.map(function(action) {
    // returns a promise with a then already attached
    return collectionActions.find({
      eventid: action.eventid
    }).then(function(e, actionsFound) {
      if (actionsFound.length == 0) {
        // returns another promise that will resolve up to outer promises
        return collectionActions.insert(action, function(err, result) {
          // Finally resolve a value for outer promises
          return 'insert action : ' + action._id;
        });
      } else {
        // A different value to resolve with if the above promise
        //  is not required
        return 'some other message for ' + action._id;
      }
    });
  })
]).then(function(results) {
  // Log out all values resolved by promises
  console.log(results);
});

更新:在澄清问题之后,听起来您只需将承诺链接在一起而不是并行运行。



// Iterate over actionList
actionList.reduce(function(promise, action) {
  // Chain promises together
  return promise.then(function(results) {
    return collectionActions.find({
      eventid: action.eventid
    }).then(function(e, actionsFound) {
      if (actionsFound.length == 0) {
        // returns another promise that will resolve up to outer promises
        return collectionActions.insert(action, function(err, result) {
          // Finally resolve a value for outer promises
          return results.push('insert action : ' + action.sourceName);
        });
      } else {
        // A different value to resolve with if the above promise
        //  is not required
        return results.push('some other message for ' + action.sourceName);
      }
    });
  });
}, Promise.resolve([])).then(function(results) {
  // Log out all values resolved by promises
  console.log(results);
});




答案 1 :(得分:0)

我终于通过使用递归函数得到了我的解决方案。

var currentIndex = 0;

var searchAndInsert = function(actionList)
{
    var action = actionList[currentIndex];
    if (typeof actionList[currentIndex] != "undefined")
    {
        collectionActions.find(
            {eventid : action.eventid}, 
            function(e,actions)
            {
                console.log("find ended")

                if (actions.length == 0)
                {
                    collectionActions.insert(action, function(err, result)
                    {
                        console.log("insert action : " + action.sourceName);
                        currentIndex++;
                        if (typeof actionList[currentIndex] != "undefined")
                            searchAndInsert(actionList);
                    })
                }
                else
                {
                    currentIndex++;
                    if (typeof actionList[currentIndex] != "undefined")
                        searchAndInsert(actionList);
                }
            }
        )
    }
};