mongoose – 链接承诺

我正在寻找关于如何链接使用MongoDB / mongoose的“查找或创build”function的承诺的build议。

我目前尝试过:

userSchema.statics.findByFacebookIdOrCreate = function (facebookId, name, email) { var self = this; return this.findOne({facebookId: facebookId }).exec() .then(function (user) { if (!user) { return self.model.create({ facebookId: facebookId, name: name, email: email }).exec().then(function (user) { return user; }); } return user; }); }; 

我从我的(node / express)API端点调用它:

  User.model.findByFacebookIdOrCreate(fbRes.id, fbRes.name, fbRes.email).then(function (user) { return res.sendStatus(200).send(createTokenForUser(user)); }, function (err) { return res.sendStatus(500).send({ error: err }); }); 

问题是:

  1. 即使用户从findOne查询中为空,创build也不会被调用
  2. 我不确定我是否使用正确的承诺风格/最有效的编码风格
  3. 我是否正确地处理错误,例如只是在最高级别,还是我需要在每个级别都做到这一点

任何人都可以看到我做错了什么,我怎么能做得更好?

谢谢。

UPDATE

问题的原因是这样的

 self.model.create(...) 

应该是(没有模型参考)

 self.create(...) 

但是,现在我需要知道我在做什么error handling错误 – 我可以看到一个错误正在发生,但我看不出原因。

我仍然有一些错误发生,我知道,因为我得到500的状态

 return res.sendStatus(500).send({ error: err }); 

但实际的错误消息/细节是空的。

问题可能在于:

  1. 创build方法返回一个承诺,它没有方法exec
  2. 如果你想在你的自定义方法中使用then() ,你必须返回一个promise,但是你要返回一个mongoose文档: return user;

这将始终返回一个承诺,它允许你在你的方法之后使用then() (你将不得不添加mpromise模块):

 userSchema.statics.findByFacebookIdOrCreate = function (facebookId, name, email) { var self = this; var Promise = require('mpromise'); var promise = new Promise; this.findOne({facebookId: facebookId }).exec() .then(function (user) { if(user) { promise.fulfill(user); return; } self.model.create({ facebookId: facebookId, name: name, email: email }) .then(function (user) { promise.fulfill(user); return; }); }); return promise; }; 

希望这可以帮助你

你的问题(和@EduardoRodríguez的后续答案)帮助我解决了类似的问题,所以欢呼! 但是,使用最新的mongoose版本+ ES6解构和箭头function,我可以把它归结为类似于以下内容:

 userSchema.statics.findByFacebookIdOrCreate = function (facebookId, name, email) { var User = this; return User.findOne({facebookId}) .then(user => user || User.create({facebookId, name, email})); }; 

…接着:

 User.findByFacebookIdOrCreate(fbRes.id, fbRes.name, fbRes.email) .then(user => res.sendStatus(200).send(createTokenForUser(user)) .catch(error => res.sendStatus(500).send({error}); 

注意:这涉及到通过configurationmongoose使用本地ES6承诺:

 mongoose.Promise = global.Promise; 

我对此还是比较陌生的,但希望这有助于其他人前进(这对我有用)。