2014-11-23 186 views
4

我正在寻找关于如何链接使用mongodb/mongoose“查找或创建”功能的承诺的建议。猫鼬 - 链接承诺

我已经试过目前:

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; 
    }); 
}; 

而且我把它从我的(节点/快递)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查询中为null,创建永远不会被调用
  2. 我是n OT确保我使用的是正确的诺言风格/最有效的编码风格
  3. 我是否正确如处理错误只在顶层或者我需要在各个层面做

谁能明白我做错了,我怎么能做得更好?

谢谢。

UPDATE

问题的原因是,

self.model.create(...) 

应该是(无参考模型)

self.create(...) 

不过,我现在需要知道我” m做错误处理错误 - 我可以看到发生错误,但我看不到原因。

我仍然有存在的一些错误,我知道,因为我得到的500

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

状态,但实际的错误信息/细节是空的。

+0

1.尝试'return self.model.create(...' 2.链接承诺时,总是返回一个新的承诺或最终的值 3.最后有一个单一的错误函数就好了 – Ivancho 2014-11-23 22:38:41

+0

谢谢,我原本有这样的回报,但它没有帮助,只是拿出来看效果。 – prule 2014-11-23 22:40:55

+0

我已经编辑了这个问题,让回来的回来。其他想法? – prule 2014-11-23 22:42:47

回答

2

的问题可能是:

  1. 创建方法返回一个承诺和它好好尝试一下有方法EXEC
  2. 如果你想在你的自定义的方法使用则()你必须返回一个承诺,但你要返回一个猫鼬文档:返回用户;

这将始终返回一个承诺,它可以让你的方法后,使用则()(您必须添加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; 
}; 

希望这可以帮助您

+0

这看起来很像[deferred antipattern](http://stackoverflow.com/q/23803743/1048572) – Bergi 2015-03-26 17:36:31

0

您的问题(以及来自@EduardoRodríguez的后续答案)帮助我解决了类似的问题,所以欢呼!但是,使用最新版本的猫鼬+ ES6解构和箭头的功能,我能得到它下降到一个类似于以下内容:

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}); 

注:此不包括通过配置猫鼬使用本地ES6承诺:

mongoose.Promise = global.Promise; 

我仍然很新的这一点,但希望这可以帮助别人前进(我的作品)。