【问题标题】:Node.js Mongoose Promise getting lostNode.js Mongoose Promise 迷路了
【发布时间】:2018-03-07 10:11:20
【问题描述】:

我有一个带有 mongoDB 的 Node.js API。有一个路由可以创建一个用户并且需要对密码进行哈希处理,为此我使用了 bcryptjs 包。

路线如下所示:

router.route('/user')

    .post(function(req, res) {
        if(req.body.password === req.body.passwordConfirm) {
            userManager.addUser(req.body)
                .then(function(response) { // waiting for the result of the mongoDB save
                    res.send({data:response});
                });
         } else {
             res.send({err:'passwords do not match'});
         }
     })

和 userManager.addUSer:

this.addUser = function(userobject) {
    bcrypt.genSalt(10, function(err, salt) { // generate a salt
        if(err !== null) {
            console.log(err);
        } else {
            bcrypt.hash(userobject.password_hash, salt, function(err, hash) { // hash pw
                if(err !== null) {
                    console.log(err);
                else {
                    userobject.password_hash = hash; // store hash in user obj
                    var user = new User(userobject);
                    return user.save().catch(function(err){ // save user in mongoDB
                        console.log(err);
                    });
                }
            });
        }
    });
};

我收到一条错误消息:“无法读取未定义的属性 'then'”,这告诉我我没有收到来自 addUser 的承诺。我看了看,遗憾的是 bcryptjs 不使用承诺,但是,猫鼬会。 (添加这个:

var mongoose = require('mongoose').Promise = Promise;

没有帮助)

我尝试用reject 和resolve 将函数包装在一个promise 中,但这给出了这个错误:“TypeError: Promise resolver undefined is not a function”。

如何获得 mongoose 的 save() 函数返回到 post 路由中的 .then() 的承诺?我尝试在两个 bcrypt 函数前面添加 return ,但这也没有用..

欢迎提出任何建议!

【问题讨论】:

  • 你没有从你的this.addUser返回一个Promise。
  • 要清楚,你不会从this.addUser返回任何东西
  • @Jaromanda X 是的,我现在明白了,我是 Promise 的新手,我想我迷失了不支持 Promise 的 API..

标签: javascript node.js mongoose promise bcrypt


【解决方案1】:

您的addUser 函数永远不会将承诺返回给它的调用者。您正在通过bcrypt.hash 回调函数执行return,但这与addUser 的返回值无关。

看起来addUser 必须使用一些未启用 Promise 的 API,因此您只能使用 new Promise,类似这样的事情(请参阅 *** cmets):

this.addUser = function(userobject) {
    return new Promise(function(resolve, reject) { // ***
        bcrypt.genSalt(10, function(err, salt) { // generate a salt
            if(err !== null) {
                reject(err);                       // ***
            } else {
                bcrypt.hash(userobject.password_hash, salt, function(err, hash) { // hash pw
                    if(err !== null) {
                        reject(err);               // ***
                    else {
                        userobject.password_hash = hash; // store hash in user obj
                        var user = new User(userobject);
                        resolve(user.save());      // *** save user in mongoDB
                    }
                });
            }
        });
    });
};

还请注意,我没有 addUser 只是吞咽错误;相反,它们被传播给调用者。调用者应该处理它们(即使“处理”只是记录)。

【讨论】:

    【解决方案2】:

    您不会从 this.addUser 返回 Promise,您必须将基于 bcrypt 的回调转换为 Promise。您可以使用例如转换整个 bcrypt API 以支持基于 Promise 的函数。蓝鸟库的promisifyAll,或者像这样使用new Promise手动完成:

    this.addUser = function(userobject) {
      return new Promise((resolve, reject) => {
          bcrypt.genSalt(10, (err, salt) => {
            if (err) {
              reject(err);
            } else {
              bcrypt.hash(userobject.password_hash, salt, function(err, hash) {
                if (err) {
                  reject(err)
                } else {
                  resolve(hash)
                }
              })
            }
          });
        })
        .then(hash => {
          userobject.password_hash = hash; // store hash in user obj
          var user = new User(userobject);
          return user.save() // save user in mongoDB
        })
        .catch(function(err) {
           console.log(err);
        });
    }
    

    或者那样:

    this.addUser = function(userobject) {
      return new Promise((resolve, reject) => {
          bcrypt.genSalt(10, (err, salt) => {
            if (err) {
              reject(err);
            } else {
              resolve(salt);
            }
          });
        })
        .then(salt => {
          return new Promise((resolve, reject) => {
            bcrypt.hash(userobject.password_hash, salt, function(err, hash) {
              if (err) {
                reject(err)
              } else {
                resolve(hash)
              }
            })
          })
        })
        .then(hash => {
          userobject.password_hash = hash; // store hash in user obj
          var user = new User(userobject);
          return user.save()  // save user in mongoDB
        })
        .catch(function(err) {
          console.log(err);
        });
    }
    

    【讨论】:

      【解决方案3】:

      在对 bcryptjs 的更改日志进行更多挖掘后,我发现他们添加了 Promise,但没有更新文档。如果省略回调,则 genSalt en hash 方法将返回一个 Promise。这将转化为:

      this.addUser = function(userobject) {
          return bcrypt.genSalt(10).then((salt) => {
              return bcrypt.hash(userobject.password, salt).then((hash) => {
                  userobject.password_hash = hash;
                  var user = new User(userobject);
                  return user.save();
              });
          });
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-03-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-08
        • 1970-01-01
        • 2013-05-19
        • 2013-06-03
        相关资源
        最近更新 更多