【问题标题】:Async function in mongoose pre save hook not working猫鼬预保存挂钩中的异步功能不起作用
【发布时间】:2018-07-25 18:02:31
【问题描述】:

在预保存挂钩中调用异步函数将返回给我undefined 以获取密码。我在这里从根本上误解了async 吗?我已经在我的应用程序的其他领域成功地使用了它,它似乎工作正常......

userSchema.pre('save', function (next) {

  let user = this

  const saltRounds = 10;

  const password = hashPassword(user)
  user.password = password;

  next();

})


async hashPassword(user) {

    let newHash = await bcrypt.hash(password, saltRounds, function(err, hash) {

    if (err) {
      console.log(err)
    }

    return hash    

  });

  return newHash

}

【问题讨论】:

  • 你明白const password = hashPassword(user) 将是一个Promise - 因为这是async 函数返回的(立即) - 因此,你将设置user.password = a_promise 和在 promise 解决之前调用 next - 下一个问题是,pre save hook 是否理解 promises
  • 在这种情况下,我需要使用 password.then(user.password = password) 吗?这是有道理的,但我认为我需要更好地理解异步/承诺
  • 确实,然后调用 next inside .then ... 你可以 avoid .then 通过 userSchema.pre('save', async function (next) { - 然后你可以 const password = await hashPassword(user) - 在功能上,这(几乎0与 .then 模式相同
  • 知道了。现在说得通了。
  • 当然,您的代码中的其他错误包括:1 - async hashPassword(user) { - 但用户从未在该函数中使用。 2 - 该函数从哪里获得saltRounds? 3 - .hash 的回调将返回哈希,无论是否有错误

标签: javascript node.js mongoose


【解决方案1】:

Mongoose 钩子允许在其中使用异步函数。它对我有用。请注意,异步函数中不需要“下一个”回调参数,因为该函数是同步执行的。

这是问题中发布的代码的正确 async/await 版本。请注意,更正以粗体标记:

userSchema.pre('save', async function () {
  
  let user = this;

  const saltRounds = 10;

  const hashed_password = await hashPassword(user.password, saltRounds);

  user.password = hashed_password;

}); // pre save hook ends here

async hashPassword(password, saltRounds) {

  try {

    let newHash = await bcrypt.hash(password, saltRounds);

  } catch(err){

    // error handling here

  }

  return newHash;

}

【讨论】:

    【解决方案2】:

    只是为了清理一下:

    userSchema.pre('save', function(next) {
        if (!this.isModified('password')) {
            return next();
        }
    
        this.hashPassword(this.password)
            .then((password) => {
                this.password = password;
                next();
            });
    });
    
    userSchema.methods = {
        hashPassword(password) {
            return bcrypt.hash(password, 10);
        },
    }
    
    • then 中使用箭头函数时可以删除let user = this
    • 当使用bcrypt.hash() 没有回调时,它会返回一个promise。
    • hashPassword 的异步在使用 .then 时是多余的

    【讨论】:

      【解决方案3】:

      我认为您需要处理 hashPassword 返回的承诺:

       hashPassword(user)
       .then(password => {user.password = password
                          next()}
       )
      

      我认为您不能将 userSchema.pre 变成异步函数。

      【讨论】:

      • 阅读文档,在“串行预挂钩”的情况下,对 next 的调用会继续“流程” - 所以无论如何返回什么都无关紧要
      猜你喜欢
      • 2021-03-10
      • 1970-01-01
      • 2017-08-19
      • 2016-07-14
      • 1970-01-01
      • 1970-01-01
      • 2018-03-04
      • 2015-11-16
      • 2015-12-11
      相关资源
      最近更新 更多