JACKY
JACKY

Reputation: 41

Can't Chain the promise

I get no idea why I can't chain the promise properly, here is my code

app.post('/login', urlencodedParser, async (req, res) => {
  // authenticate is async function that return promise
  model.authenticate(req.body.uname, req.body.pword)
    .then(function (result) {
      console.log(result);
      // ... some codes
    });
});

// here is the function authenticate
async function authenticate(uname, pword) {
  User.find({username: uname}, 'password', function (err, result) {
    if (err !== null){
      return new Promise(function (resolve, reject) {
        resolve(false);
      });
    }
    else{
      if (pword === result[0].password){
        console.log("Correct Password!");
        return new Promise(function (resolve, reject) {
            resolve(true);
        });
      }

But the output in my console is

undefined
Correct Password!

,which indicate that .then() is implemented before authenticate is finished. So how can I code it in a better way? thank you very much!

Upvotes: 4

Views: 64

Answers (3)

ninhjs.dev
ninhjs.dev

Reputation: 8603

With async:

async function authenticate(uname, pword) {
    return await User.find({ username: uname }, 'password').then(function (result) { ... })
};

Without async:

function authenticate(uname, pword) {
    return User.find({ username: uname }, 'password').then(function (result) { ... })
};

Upvotes: 1

Hannan
Hannan

Reputation: 514

Issue is that you are returning promise from a callback function. There is no point in doing that. You need to return a promise from the authenticate function & resolve/reject it once the function does the intended work. Look at the following code, it should fix your issue

/* This function doesnt need to be async */
function authenticate(uname, pword) {
  return new Promise((resolve, reject) => {
    User.find({username: uname}, 'password', function (err, result) {
      if (err !== null) {
        /* I think this should be reject(err) but since you wish to have it resolved in your code, i have kept resolve()*/
        resolve(false);
      }
      else {
        if (pword === result[0].password) {
          console.log("Correct Password!");
          resolve(true);
        }
      }
    })
  });
}

Upvotes: 2

Alexander O'Mara
Alexander O'Mara

Reputation: 60577

The problem is the body of your authenticate function does not return anything. It calls an asyncronous function, which uses a callback, then returns an implicit promise the resolves to undefined.

async function authenticate(uname, pword) {
  User.find({username: uname}, 'password', function (err, result) {
    // This will run sometime after authenticate returns
  });
}

You need to wrap the User.find call in a promise.

// here is the function authenticate
async function authenticate(uname, pword) {
  return new Promise(function (resolve, reject) () {
    User.find({username: uname}, 'password', function (err, result) {
      if (err !== null){
        resolve(false);
      }
      else{
        if (pword === result[0].password){
          console.log("Correct Password!");
          resolve(true);
        }
        // Also add an else here, to ensure the promise always ends:
        else {
          resolve(false);
        }
      }
    });
  });
}

Upvotes: 1

Related Questions