【问题标题】:mongoDB promise gets returned too early [closed]mongoDB承诺过早返回[关闭]
【发布时间】:2014-03-11 01:48:54
【问题描述】:

我刚开始尝试在我的 Node.js 应用程序上实现 Promises。现在我正在检查用户和密码是否存在,然后使用 mongodb 查找它们,如果没有找到用户,它会设置 promise.reject() 但它太早地返回承诺并且它仍处于挂起状态。如果有人可以帮助我或给我有关如何重构的想法,将不胜感激。

https://gist.github.com/joshbedo/8957056

【问题讨论】:

  • 附带说明:使用比 md5 哈希更强大的密码作为密码,我也不会依赖 uuid 作为确认码。
  • 是的,只是为了让它运行,而且我不想暴露我的安全模块:p
  • 确保在第一次 defer.reject(err) 之后返回,否则 defer.reject() 将在 defer.reject("User not found") 中再次被调用
  • 感谢各位指点!

标签: node.js mongodb promise


【解决方案1】:

当它仍处于待处理状态时,它返回承诺是预期的行为。

您应该使用then() 来检查承诺解决方案。

另外一点是你在开始使用promise的时候不应该使用传统的mongo接口,而是promisifyCollection原型的所有方法,这样你就可以返回mongo find方法创建的Promise及其链可以的。否则我看不到使用承诺的意义。您这样做的方式不会减少您必须编写的代码量。

顺便说一句,恕我直言,您应该使用 bluebird 而不是 Q,因为它是目前唯一一个不是特别慢的 Promise 库。

例子:

在 db.js 中

var mongoClient = require('mongodb').MongoClient;
var collection  = require('mongodb').Collection;

var Promise     = require('bluebird');

// We promisify everything. Bluebird add ***Async function which return promises.
Promise.promisifyAll(collection.prototype);
Promise.promisifyAll(mongoClient);

//In mongodb cursor is not built from protoype I use to promisify it each time. Not necessary if you don't use cursors.
collection.prototype._find = collection.prototype.find;
collection.prototype.find = function() {
  var cursor = this._find.apply(this, arguments);
  cursor.toArrayAsync = Promise.promisify(cursor.toArray, cursor);
 return cursor;
};

//then you connect to the DB and exports your collections...

在其他地方,以你为例:

this.loginUser = function(user) {
  var userid = user.userid,
  var password = (user.password) ?
    crypto.createHash("md5").update(user.password).digest("hex"):
    undefined
  var rememberme = user.rememberme;

  if(userid && password) {
    // we directly return the promise from mongodb, that we chain with a then
    return db.users.findOneAsync({ email: userid, password: password }) // return a promise that we chain
    .then(function(user) { // that we chain
      if(user) {
        var logincode = uuid.v4(),
        var token = jwt.encode({email: userid, password: password}, secret);

        if(rememberme) {
          res.cookie("clogincode", logincode, { magAge: 900000 } );
        }
        return user;  // return in a then callback will just resolve the promise
      } else {
        throw  new Error('User not found'); // throwing in a then callback will just reject the promise
      }
    }); // end of the then, then return a promise that we return (with the return keyword above)
  } else {
    return Promise.reject("Username or Password was not entered"); // this is the only case where we have to actually create a promise ourself
  }
}

【讨论】:

  • 你碰巧知道 IcedCoffeeScript 的 await 和 defer 使用什么吗?是的,我希望它检查是否设置了变量,然后查询数据库,然后检查结果是否满足或拒绝。似乎我正在向我的代码库添加更多内容以尝试实现该功能。
  • 你对 mongo 的库有偏好吗,比如 promisify-mongo
  • 我个人使用 bluebird 的 promisify 方法,它基本上可以使用节点样式回调对任何库进行 promisify。我不知道Q是否有同样的实用功能。
  • 你有什么可以展示的例子吗?
  • 我现在在玩手机,但我会在我在家时告诉你:)
猜你喜欢
  • 1970-01-01
  • 2019-06-15
  • 2016-09-13
  • 2016-06-10
  • 2018-01-09
  • 1970-01-01
  • 2016-01-24
  • 2016-06-15
  • 2018-03-27
相关资源
最近更新 更多