猫鼬 - 链接承诺

时间:2014-11-23 21:27:50

标签: javascript node.js mongodb mongoose promise

我正在寻找有关如何将承诺链接到"查找或创建"功能使用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;
  });
};

我从我的(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. 即使user在findOne查询中为null,也永远不会调用create
  2. 我不确定我是否使用了正确的承诺风格/最有效的编码风格
  3. 我是否正确处理错误,例如只是在顶层,或者我是否需要在每个级别进行错误
  4. 任何人都可以看到我做错了什么,以及我怎样才能做得更好?

    感谢。

    更新

    问题的原因是

    self.model.create(...)
    

    应该是(没有模型参考)

    self.create(...)
    

    但是,我现在需要知道我在错误处理方面做错了什么 - 我可以看到错误发生了,但我看不出原因。

    我仍然遇到一些错误,因为我的状态为500

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

    但实际的错误消息/详细信息为空。

2 个答案:

答案 0 :(得分:2)

问题可能是:

  1. 创建方法会返回一个承诺,但它没有方法 exec
  2. 如果您想在自定义方法中使用 then(),则必须返回一个承诺,但是您要返回一个mongoose文档:返回用户;
  3. 这将始终返回一个承诺,它允许您在方法后使用 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;
    };
    

    希望这有助于你

答案 1 :(得分:0)

你的问题(以及@EduardoRodríguez的后续回答)帮助我解决了类似的问题,所以欢呼!但是,使用最新的mongoose版本+ 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});

注意:这确实涉及通过使用以下命令配置mongoose来使用本机ES6承诺:

mongoose.Promise = global.Promise;

我对此仍然很陌生,但希望这有助于其他人继续前进(对我有用)。