【问题标题】:multiple async mongo request in nodejsnodejs中的多个异步mongo请求
【发布时间】:2013-05-15 16:28:03
【问题描述】:

如何连续编写多个查询?

喜欢一个

Space.findOne({ _id: id }, function(err, space) {
    User.findOne({ user_id: userid }, function(err, user) {
        res.json({ space: space, user: user});
    });
});

更多的请求和逻辑看起来不太好

如何正确完成?

我听说了一些关于承诺的事情,但我不知道。

谢谢

【问题讨论】:

  • 您希望函数彼此异步执行还是像示例代码中那样一起执行?

标签: javascript node.js mongodb asynchronous


【解决方案1】:

如果您使用的是支持 Promises 的 Node.js 4+,则可以将查询包装在 Promise 中。

queryPromise = function(findQueryCursor) {
  return new Promise(function(resolve, reject) {
    findQueryCursor.toArray(function(err, data) {
      resolve(data);
    });
  });
};

然后,创建一个由查询组成的 Promises 数组:

promiseAr = [];
promiseAr.push(
  queryPromise(
    db.collection('dbname').find(query1)
  )
);
promiseAr.push(
  queryPromise(
    db.collection('dbname').find(query2)
  )
);

然后调用

Promise.all(promiseAr)
.then(function(dataArray) {
   // results of query1 in dataArray[0]
   // results of query2 in dataArray[1]
})
.catch(function(err) {
   // catch errors
});

查询将并行发送到 MongoDB,所有查询完成后将调用“.then”函数。

你必须这样做的原因是因为 .find() 函数返回一个游标,然后你必须调用 .toArray() 来检索数据。 .toArray() 本身是异步的,所以如果你想使用 Promise.all,你必须将它包装在 Promise 中。

【讨论】:

  • 很棒的代码。花了半个小时寻找答案,这是唯一更新的。这应该被投票给顶部。谢谢!
  • 我应该为所有承诺使用一个连接实例还是为每个承诺使用一个实例?当我在 Promise 中创建连接实例时,我收到错误响应“在调用 MongoClient.prototype.db 之前必须连接 MongoClient”
  • 我不再和 Mongo 打交道了。我的猜测是,在发送查询之前,您需要先等待连接返回。将连接包装在 Promise 中,然后执行 connectPromise().then(result) ... 然后发送您的查询。如果您使用的是 ES6,则可以使用一些人认为更直接的 async / await 语法。它与 Promise 相同,语法更简洁。
【解决方案2】:

@Benjamin 的方法是正确的。 Mongoose 还提供了populate 方法,该方法可以获取多个通过 id 相互关联的对象。这也是并行发生的,是多个查询的特例。有关更多示例,请参阅http://mongoosejs.com/docs/populate.html

【讨论】:

    【解决方案3】:

    当我遇到类似问题时,我使用了 async 库。

    async.parallel([
        function(callback){
           Space.findOne({ _id: id }, callback);
        },
        function(callback){
            User.findOne({ user_id: userid },callback);
        }
    ],
    function(err, results){
        res.json({space:results[0],user:results[1]});
    });
    

    如果您想要顺序执行,也可以使用 async.series。

    【讨论】:

    • 注意,使用.bind 可以缩短这段代码,但为了清楚起见,我会避免这样做。
    • 注意 2015 年,两年后 - 我会用承诺来做这件事,它们是解决这个问题的更优雅的解决方案。如果有人关心发表评论,我会用承诺添加答案。
    猜你喜欢
    • 1970-01-01
    • 2015-01-17
    • 1970-01-01
    • 2013-10-23
    • 2012-05-26
    • 2018-04-10
    • 1970-01-01
    • 1970-01-01
    • 2011-06-06
    相关资源
    最近更新 更多