0

I'm running into a strange problem with a very simple and straightforward JS code. Here, I'm trying to look up a given (email) value against a database and return a boolean true if a record with that value exists:

// utils/isEmailInDB.js
import User from '../models/user';

const isEmailInDB = (email) => {
  let emailExists;
  User.findOne({ emails: email }).then((existingUser) => {
    if(existingUser) { emailExists = true; } else { emailExists = false; }
  });
  return emailExists;
};
export default isEmailInDB;

In another file, I'm calling this function and logging the returned value to the screen:

// routes/mail-routes.js
import express from 'express';
import sendEmail from '../utils/sendEmail';
import isEmailInDB from '../utils/isEmailInDB';

import { check, validationResult } from 'express-validator';

const router = express.Router();

router.post('/', [
  check('to').isEmail(),
], (req, res) => {
  const errors = validationResult(req);
  const { to = '', pageURL = '/' } = req.body;
  if (!errors.isEmpty()) {
    res.redirect(pageURL + '?verify=1');
  } else {
    // Generate token
    // Check if email exists in db
    const existsInDB = isEmailInDB(to);
    console.log('EMAIL EXISTS?', existsInDB);
    sendEmail(to).then(() => {
      res.redirect(pageURL + '?verify=2');
    }).catch((err) => {
      res.redirect(pageURL + '?verify=1');
    });
  }
});

module.exports = router;

With this line in the second snippet above: console.log('EMAIL EXISTS?', existsInDB);, I expect to see one of the following outputs upon execution, depending on whether the email exists in DB:

EMAIL EXISTS? true

EMAIL EXISTS? false

However, no matter what I try, the line keeps returning undefined. Even when the email being looked up exists. What could I be doing wrong?

Community
  • 1
  • 1
TheLearner
  • 2,813
  • 5
  • 46
  • 94

2 Answers2

2

You need to use Promises or asyn-await with the isEmailInDB function, because it is NOT waiting for the User.find to complete. Also, when you are calling the function it is again not waiting for the async function to complete as well.

const isEmailInDB = async (email) => {
  const existingUser = await User.findOne({ emails: email });
  return !!existingUser;
};

In the route:

router.post('/', [
  check('to').isEmail(),
], async (req, res) => {
    .
    .
    const existsInDB = await isEmailInDB(to);
    .
    .
});
Aritra Chakraborty
  • 12,123
  • 3
  • 26
  • 35
1

You are getting undefined as the the return statement is immediately executed and at that time existingUser is undefined. What you could is instead return a promise a true or false value and use this promise in your mail routes file.

Update your isEmailInDB code.

// utils/isEmailInDB.js
import User from '../models/user';

const isEmailInDB = (email) => {
  let emailExists;
  return User.findOne({ emails: email })
  .then((existingUser) => {
     return { emailExists = !!existingUser };

  });
};
export default isEmailInDB;

and in your mail routes use this instead

const existsInDB = isEmailInDB(to);
existsInDB.then((existsInDB) => {
  console.log('EMAIL EXISTS?', existsInDB);
  sendEmail(to).then(() => {
    res.redirect(pageURL + '?verify=2');
  }).catch((err) => {
    res.redirect(pageURL + '?verify=1');
  });
})
alt255
  • 3,396
  • 2
  • 14
  • 20