如何确保在mongodb查询完成之前函数不会返回

时间:2015-01-20 19:02:40

标签: node.js mongodb

我有一个用户模型函数all,它返回数组中的所有用户。

User = {
  all: function() {
    var users = [];

    globalLibrary.db.collection('users').find({}).toArray(function(err, items) {
      test.equal(null, err);
      users = items;
    });

    return users;
  }
}

我想确保在mongodb查询完成之前函数没有完成或返回。

目前,此函数只返回[],并异步查询mongodb。我希望函数等到函数完成查询完成后返回并且数组中充满了用户。

注意:

globalLibrary.db只是一个缓存的mongodb连接。


我使用promises的解决方案

由于有些人将问题视为副本,我会在问题中写下我的答案。希望不熟悉异步编程的其他人发现这很有用。

问题

  

关键是你需要使用回调 - 没有办法阻止   在异步的东西上。 (...) - Aaron Dufour

我上面写的函数User.all()将返回空数组,因为在mongodb查询发生时没有停止进程。有一些原始方法可以阻止这个过程。

你可以使用setTimeout()加速一些hacky东西。这种方式很糟糕,因为你必须使用一些可能高于你需要查询mongodb的实际时间的任意时间。简单地说,它的速度较慢。

您还可以使用@AaronDufour在评论中链接的一些基于事件的内容(现已删除)。所以你可以用一对事件发射器和一个监听器替换setTimeout()方式。 @Someone指出你不应该在node.js中使用它来阻止函数。

现在最后,解决这个问题的传统方法是使用the answer below指出的回调。这很好,但是一旦你开始将多个回调堆叠在一起,回调就会很快失控。

我正在使用https://github.com/kriskowal/q进行承诺。虽然使用promises并不能解决所有回调问题,但它看起来最像简单的同步编程风格,我认为这是一个巨大的优势。

首先npm install --save q开始使用Q包。

这是我的新User.all()功能。

var Q = require('q')

var Users = {
  all: function() {
    var deferred = Q.defer();

    globalLibrary.db.collection('users').find({}).toArray(function(err, items) {

      if (err) {
        deferred.reject(new Error(err));
      } else {
        deferred.resolve(items);
      }
    });

    return deferred.promise;
  }
}

现在,如果您想使用User.all()

User.all()
.then(function (docs) {
  // docs is the array of returned users from mongodb query.
  console.log(docs);

}, function(error) {
  // do something if there's an error.
}, function(progress) {
  // do something while the query is running.
});

1 个答案:

答案 0 :(得分:2)

在node.js中执行此操作的首选方法是包含它的异步性质并传递回调函数。一些体面的教程(最后一个包括mongodb示例):

http://justinklemm.com/node-js-async-tutorial/

http://msdn.microsoft.com/en-us/magazine/dn754378.aspx

如果你认为你必须反对并且同步,我会看一下node.js和mongodb的这个同步库:

https://www.npmjs.com/package/mongo-sync