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 }); });
问题是:
- 即使用户从findOne查询中为空,创build也不会被调用
- 我不确定我是否使用正确的承诺风格/最有效的编码风格
- 我是否正确地处理错误,例如只是在最高级别,还是我需要在每个级别都做到这一点
任何人都可以看到我做错了什么,我怎么能做得更好?
谢谢。
UPDATE
问题的原因是这样的
self.model.create(...)
应该是(没有模型参考)
self.create(...)
但是,现在我需要知道我在做什么error handling错误 – 我可以看到一个错误正在发生,但我看不出原因。
我仍然有一些错误发生,我知道,因为我得到500的状态
return res.sendStatus(500).send({ error: err });
但实际的错误消息/细节是空的。
问题可能在于:
- 创build方法返回一个承诺,它没有方法exec
- 如果你想在你的自定义方法中使用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;
我对此还是比较陌生的,但希望这有助于其他人前进(这对我有用)。