node.js使用mongoose

时间:2018-01-06 14:23:29

标签: javascript node.js express mongoose

我有一个看起来像这样的功能,至少它现在起作用了。

exports.changePassword = (req, res) => {
  const { token, password, confirmPassword } = req.body

  User.findOne({resetPasswordToken: token}, (err, user)=>{
    if(!user){
      return res.status(400).send({
        msg: 'Invalid token or token has been used!'
      })
    }

    const hash_password = bcrypt.hashSync(password, 10)
    User.findOneAndUpdate({_id: user._id}, 
      {hash_password}, 
      (err, result)=>{

        if(err){
          return res.status(400).send({
            msg: err
          })
        }

        User.findOneAndUpdate({_id: user._id},
          {resetPasswordToken: ''},
          (err, result)=>{
            if(err){
              return res.status(400).send({
                msg: err
              })
            }

            res.status(200).json({
              status: 1,
              data: 'Your password has been changed.'
            })
          }
        )
      })
  })
}

我写这段代码感觉很糟糕,因为我觉得它有几个问题:

  1. 回调地狱
  2. 重复错误处理代码
  3. 对于第一个问题,我可以使用完成参数吗?并做一些链接?而且有时我怀疑我需要处理每一个错误的回调。你会如何重写上面的功能以变得更优雅?

2 个答案:

答案 0 :(得分:2)

你可以使用Mongoose的promises,这将有助于你的回调地狱:

exports.changePassword = (req, res) => {
  const { token, password, confirmPassword } = req.body

  User.findOne({resetPasswordToken: token}).then((user)=>{
    // do stuff with user here 

    const hash_password = bcrypt.hashSync(password, 10)
    // Now chain the next promise by returning it
    return User.findOneAndUpdate({_id: user._id}, {hash_password});
  }).then((result)=>{
    // Now you have the result from the next promise, carry on...
    res.status(200).json({
      status: 1,
      data: 'Your password has been changed.'
    })
  }).catch(err => {
    // Handle any errors caught along the way
  });
}

由于这些是承诺,你可以通过使用ES6 async / await语法实际上使它更整洁:

// Note this now has the async keyword to make it an async function
exports.changePassword = async (req, res) => {
  const { token, password, confirmPassword } = req.body

  try {
    // Here is the await keyword
    const user = await User.findOne({resetPasswordToken: token});

    // do stuff with user here 

    const hash_password = bcrypt.hashSync(password, 10)

    // Now the next promise can also be awaited
    const result = await User.findOneAndUpdate({_id: user._id}, {hash_password});

    // Finally send the status
    res.status(200).json({
      status: 1,
      data: 'Your password has been changed.'
    });
  } catch (err) {
    // Any promise rejections along the way will be caught here
  });
}

答案 1 :(得分:0)

为了避免这种丑陋Promise hell我们有

  

ES2017 async/await语法

你应该为这样的事情改变你的整个代码

exports.changePassword = async function (req, res){
    try {
        const { token, password, confirmPassword } = req.body

        var user = await User.findOne({resetPasswordToken: token}).exec()
        const hash_password = bcrypt.hashSync(password, 10)

        var result = await User.findOneAndUpdate({_id: user._id}, {hash_password}).exec()
        var result2 = await User.findOneAndUpdate({_id: user._id}, {resetPasswordToken: ''}).exec()

        res.status(200).json({status: 1, data: 'Your password has been changed.'})
    } catch (err) {
        res.status(400).send({msg: err }) //If some await reject, you catch it here
    }   
}