3

Hi I'm new at javascript programming.

I have a node express project, I'm trying to create a login method inside my AuthenticationController class.

My login method is like this right now:

const User = require('../models/User')

class AuthenticationController {

  async login(req, res) {
    const { email, password } = req.body
    console.log('step 1')
    var hashPassword = await userPassword(email)
    console.log(hashPassword)
    console.log('step 2')
    return res.status(200).json({ 'msg': 'Log in OK!' })

  }

  userPassword(email) {
    User.findOne({ email: email }).exec(function(err, user) {
      if (err) return err
      else return user.password
    })
  }
}

But I got an error saying that userPassword is undefined, I couldn't figure out why. So my doubts are: why this is happening, and how to do it correctly ?

I also checked out this questions, but they didn't helped me:

The error message at my console:

(node:28968) UnhandledPromiseRejectionWarning: ReferenceError: userPassword is not defined ...

(node:28968) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)

(node:28968) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Estus Flask
  • 206,104
  • 70
  • 425
  • 565
Lucas Andrade
  • 4,315
  • 5
  • 29
  • 50

2 Answers2

7

login doesn't refer to userPassword method but to the function of the same name which doesn't exist.

Promises are supposed to be be chained and they aren't. userPassword is expected to return a promise but it uses obsolete Mongoose callback API.

That UnhandledPromiseRejectionWarning is shown means that errors weren't correctly handled in login while they should. As explained in this answer, Express don't support promises so errors should be handled by a developer.

It should be:

  async login(req, res) {
      try {
        const { email, password } = req.body
        var hashPassword = await this.userPassword(email)
        return res.status(200).json({ 'msg': 'Log in OK!' })
      } catch (err) {
        // handle error
      }
  }

  async userPassword(email) {
    const { password } = await User.findOne({ email: email });
    return password;
  }
Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • Thank for your explanation, I got it now. I tried your solution but now I got this error: `TypeError: Cannot read property 'userPassword' of undefined ` I can't understand why userPassword is undefined – Lucas Andrade Feb 23 '19 at 13:38
  • 1
    This depends how you use `login` which wasn't shown in the question. I'm positive you passed it as a callback while it wasn't bound to proper context. See https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-context-inside-a-callback . In this case you don't need a class at all, it's an antipattern. Vanilla Express cannot benefit from OOP. You could make `login` and `userPassword` regular functions and that's how it's usually done. – Estus Flask Feb 23 '19 at 13:58
  • I change my class to only methods inside a module exports, worked! Do you have any link so I can read more about this antipattern in JS? Thanks – Lucas Andrade Feb 28 '19 at 12:25
  • @LucasAndrade It's not an antipattern with specific name, just a bad Express recipe I've seen numerous times. Express is functional, it cannot efficiently make use of entities represented by classes for its own API (middlewares, routes), unless you leverage some framework around it (e.g. NestJS).The use of OOP for the sake of OOP is a bad practice (it's a matter for Occam's razor). So is the use of stateless or static-only classes (they are treated as glorified namespaces, this is what modules are for). Things may be different for other frameworks and languages. – Estus Flask Feb 28 '19 at 19:04
  • 2
    This is a good answer but to answer the question of why userPassword is undefined, you were calling a FUNCTION within your class which does not exist. Once you added the `this` you are now referring to a method of your class. – ioMatrix Oct 02 '19 at 16:02
0

this error is coming because you are not handling error for the promise. Always use async/await inside try/catch block.

try{
  async login(req, res) {
    const { email, password } = req.body
    console.log('step 1')
    var hashPassword = await userPassword(email)
    console.log(hashPassword)
    console.log('step 2')
    return res.status(200).json({ 'msg': 'Log in OK!' })
  }
}catch(e){
    console.log(e)
}
Rahul Sharma
  • 9,534
  • 1
  • 15
  • 37