【问题标题】:Mongoose - chaining promisesMongoose - 链接承诺
【发布时间】:2015-01-21 13:21:15
【问题描述】:

我正在寻找有关如何使用 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. 即使用户在 findOne 查询中为 null,也永远不会调用 create
  2. 我不确定我使用的是正确的承诺风格/最有效的编码风格
  3. 我是否正确处理错误,例如仅在顶层还是我需要在每个级别都这样做

谁能看到我做错了什么,以及如何才能做得更好?

谢谢。

更新

问题的原因是

self.model.create(...)

应该是(没有模型参考)

self.create(...)

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

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

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

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

【问题讨论】:

  • 1.试试return self.model.create(... 2. 链接承诺时,总是返回一个新的承诺或最终值。 3. 最后有一个错误函数就好了。
  • 谢谢,我最初确实有那个回报,但它没有帮助。才拿出来看看效果。
  • 我已编辑问题以将退货放回原处。还有其他想法吗?
  • 嗯,这很奇怪。我以为它被调用了,但由于缺少return,您没有得到它的结果。
  • 我找到了问题的主要原因:self.model.create(...应该是self.create(...

标签: javascript node.js mongodb mongoose promise


【解决方案1】:

您的问题(以及@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;

我对此仍然很陌生,但希望这可以帮助其他人前进(它对我有用)。

【讨论】:

    【解决方案2】:

    问题可能是:

    1. create 方法返回一个承诺,它没有方法 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;
    };
    

    希望对你有帮助

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-06
    • 2015-04-15
    • 2023-01-27
    • 2016-01-17
    • 1970-01-01
    • 1970-01-01
    • 2018-02-15
    • 2016-06-21
    相关资源
    最近更新 更多