Home > database >  javascript how to use make process wait until async function finishes
javascript how to use make process wait until async function finishes

Time:11-30

now I'm making a user Authentication system, but I'm having trouble with javascript's process order. Here is my code.

const isAuthenticated = async (username, password) => {
//this User.finOne is async function
        User.findOne({ username: username }, function (err, foundUser) {
        if (err) {
            console.log(err);
        }
        else {
            if (foundUser) {
                if (foundUser.password === password) {
                    console.log("ID:", foundUser.id);
                    console.log("NAME:", foundUser.username);
                    return foundUser.id
                }
            }
            else {
                return 0;
            }
        }
    });
}

app.post("/login", async function (req, res) {
    const userName = req.body.username;
    const password = md5(req.body.password);

    let userID = await isAuthenticated(userName, password);
    
    // userID becomes undefined
    console.log("userID", userID);

    if (userID === 0 || userID == undefined) {
        const status = 401
        const message = 'Incorrect username or password'
        res.status(status).json({ status, message })
        return
    }

    const accessToken = createToken({ id: isAuthenticated(userName, password) })
    console.log("here is token", accessToken);

    const responseJson = {
        success: true,
        username: userName,
        userID: userID
    }

    res.cookie('JWTcookie', accessToken, { httpOnly: true })
    res.status(200).json(responseJson)

When a user logged in with a correct password and username, this API is supposed to return cookie. This cookie itself works fine, but the problem is that " if (userID === 0 || userID == undefined)" is processed earlier than the function isAuthenticated(). When I checked the order, isAuthenticated is processed later. To prevent this, I tried using async await, so that the job stops at let userID = await isAuthenticated(userName, password);. But this didn't work.

If anyone point out why this programming is working in this order, I really appreciate it. Thank you.

CodePudding user response:

You could make isAuthenticated throw an error when the credentials are wrong and then work with .then() and .catch() to execute your code in the order you want.

const isAuthenticated = async (username, password) => {
  User.findOne({username: username}, (err, foundUser) => {
    if (err) throw new Error(err);
    if (foundUser && foundUser.password === password) {
      console.log("ID:", foundUser.id);
      console.log("NAME:", foundUser.username);
      return foundUser.id
    }
    return 0;
  })
}

And then in your post route:

app.post('/login', async function (req, res) {
  const userName = req.body.username;
  const password = md5(req.body.password);

  isAuthenticated(userName, password)
    .then((id) => {
      if (id) {
        const accessToken = createToken({
          id: isAuthenticated(userName, password),
        });
        console.log('here is token', accessToken);
        const responseJson = {
          success: true,
          username: userName,
          userID: userID,
        };
        res.cookie('JWTcookie', accessToken, { httpOnly: true });
        return res.status(200).json(responseJson);
      } else {
        const status = 401;
        const message = 'Incorrect username or password';
        return res.status(status).json({ status, message });
      }
    })
    .catch((err) => console.log(err));
});

CodePudding user response:

The problem should be isAuthenticated isn't waiting for anything to finish execution from within itself even though it has been declared async. Hence even if you are doing this: let userID = await isAuthenticated(userName, password);, since isAuthenticated isnt returning or awaiting a Promise / any asynchronous activity inside it, the compiler would just move on and continue executing the remaining piece of code in that function. If you want the User.findOne function to be executed first you should be changing the isAuthenticated function to something similar to this:

const isAuthenticated = async (username, password) => {
        await User.findOne({ username: username }, function (err, foundUser) {
        if (err) {
            console.log(err);
        }
        else {
            if (foundUser) {
                if (foundUser.password === password) {
                    console.log("ID:", foundUser.id);
                    console.log("NAME:", foundUser.username);
                    return foundUser.id
                }
            }
            else {
                return 0;
            }
        }
    });
}
  • Related