0

Ok, so I am using Node.js, ExpressJS and MongoDB for making a website. I'm trying to make AJAX calls to check form validity (as I want to show whether the input values are valid or not on the go as the user types.) I have achieved all this up to 90%. The only thing that is not working is checking whether the username and email are already present or not in the database. My query is perfect but when I am trying to store the result given by the query (whether in the database or not) it is not happening. Here's my code : -

router.post('/signup',function(req, res){
  const username = req.body.username;
  const email = req.body.email;

  var response = [];
  var usernameTaken, emailTaken;

  User.findOne({username:username}, function(err, user){
    if (err) throw err;
    if (Boolean(user)) {
      console.log(user); // This works perfectly
      usernameTaken = true; // This does not works at all!
      console.log(usernameTaken); // Nor does this one. :/
    } else {
      usernameTaken = false;
    }
  });

  console.log(usernameTaken); // No output

  // Else part gets executed because usernameTaken does not sets to true.
  if (usernameTaken) {
    response.push({field: "username", type: "danger", message: "Sorry! This username is already taken :("});
  } else {
    response.push({field: "username", type: "success", message: "This username is now yours ;)"});
  }

  if (!isValid(email)) {
    response.push({field: "email", type: "danger", message: "Please enter a valid E-mail Address."});
  } else {
    response.push({field: "email", type: "success", message: "E-mail is valid."});
  }

  User.findOne({email:email}, function(err, user){
    if (err) throw err;
    if (Boolean(user)) {
      console.log(user); // Again this works.
      emailTaken = true; // But this does not works :(
    } else {
      emailTaken = false;
    }
  });

  // Else part gets executed because emailTaken does not sets to true.
  if (emailTaken) {
    response.push({field: "email-avail", type: "danger", message: "This E-mail address is already registered!"});
  } else {
    response.push({field: "email-avail", type: "success", message: "E-mail is valid."});
  }

  res.send(response);
});

1 Answers1

0

Remember that all functions like findOne or anything executes asynchronously meaning that what ever execution steps you put inside the callback, they will get executed anytime. Which is why your boolean values are not printed as expected outside the callbacks.

Now, one way you can work your way through is by using async/await which will basically ensure that your code stops execution until the promise is resolved. So, in a way making the whole process synchronous.

ASYNC

AWAIT

Give this a try. I used async/await to make the process synchronous.

router.post('/signup',async function(req, res){
  const username = req.body.username;
  const email = req.body.email;

  var response = [];
  var usernameTaken, emailTaken;

  const userNamePromise = new Promise((resolve, reject) => {
    User.findOne({username:username}, function(err, user){
      if (err) reject(err);
      if (Boolean(user)) {
        resolve(true)
      } else {
        resolve(false);
      }
    });
  })

  usernameTaken = await userNamePromise;

  console.log(usernameTaken);

  if (usernameTaken) {
    response.push({field: "username", type: "danger", message: "Sorry! This username is already taken :("});
  } else {
    response.push({field: "username", type: "success", message: "This username is now yours ;)"});
  }

  if (!isValid(email)) {
    response.push({field: "email", type: "danger", message: "Please enter a valid E-mail Address."});
  } else {
    response.push({field: "email", type: "success", message: "E-mail is valid."});
  }

  const emailPromise = new Promise((resolve, reject) => {
    User.findOne({email:email}, function(err, user){
      if (err) reject(err);
      if (Boolean(user)) {
        console.log(user);
        resolve(true);
      } else {
        resolve(false);
      }
    });
  })  
  emailTaken = await emailPromise;

  if (emailTaken) {
    response.push({field: "email-avail", type: "danger", message: "This E-mail address is already registered!"});
  } else {
    response.push({field: "email-avail", type: "success", message: "E-mail is valid."});
  }

  res.send(response);
});
Nandu Kalidindi
  • 6,075
  • 1
  • 23
  • 36