Skip to content
Advertisement

How to use async/await to get input from user but wait till entire condition statement is read before resolving?

I created a function that prompts the user for a URL, then validates that the entered input is actually a URL. The issue is, when I call this function from my other function, I have been able to get it to wait for user input before but it doesn’t go through the entire condition statement before returning the url.

How do I use promises/async/await to wait till my requestSiteURL() function has completed its condition statement, before setting the variable in getURL()?

const readline = require('readline').createInterface({
   input: process.stdin,
   output: process.stdout,
});

// request url from user in command prompt
const requestSiteURL = () => {
  return new Promise((resolve, reject) => {
    readline.question('Please type url: ', async (url) => {
      if (validUrl.isUri(url)) {
        readline.close();
        resolve(url);
        // if user types no, then use base url
      } else if ('No' || 'no' || 'NO') {
        url = URL;
        resolve(url);
      } else {
        reject(
          console.log(
            'Please type in a valid URL or type "no" to use base url.'
          )
        );
        requestSiteURL();
      }
    });
  });
};

// grabs all urls from original link and returns array
const getURLS = async () => {
  let url = await requestSiteURL();
  url = deleteFowardSlash(url);
  try {
    const res = await axios.get(url);
    const data = res.data;
    const $ = cheerio.load(data);

    const urlQueue = [];

    // finds all absolute links and pushs to urlQueue array
    $("a[href^='http']").each((i, elem) => {
      let link = $(elem).attr('href');
      //checks to make sure link isnt any duplicate links in urlqueue array
      link = deleteFowardSlash(link);
      uniqueLinkChecker(link, urlQueue);
    });
    return urlQueue;
  } catch (err) {
    console.error(err);
    return response.status(400).send(err);
  }
};

Answer

I think it is a matter of syntax. Here I switched the original line to use the Promise constructor correctly. Promise mdn

// request url from user in command prompt
const requestSiteURL = () => {
  return new Promise((resolve, reject) => {
    readline.question('Please type url: ', async (url) => {
      if (validUrl.isUri(url)) {
        readline.close();
        resolve(url);
        // if user types no, then use base url
      } else if (url.toLowerCase() === 'no') {
        url = URL;
        resolve(url);
      } else {
        console.log(
          'Please type in a valid URL or type "no" to use base url.'
        )
        requestSiteURL().then(resolve);
      }
    });
  });
};

Edit: Adding an async/await version. Basically I think you don’t ever have to reject. I edited the above to not reject as well. Also I’m assuming URL is the default url (this conflicts with the global URL namespace, just for the record)

// request url from user in command prompt
const requestSiteURL = async function () {
  const url = await new Promise(resolve => {
    readline.question('Please type url: ', resolve)
  })
  if (validUrl.isUri(url)) {
    readline.close()
    return url
  } else if (url.toLowerCase() === 'no') {
    return URL
  } else {
    console.log('Please type in a valid URL or type "no" to use base url.')
    return requestSiteURL()
  }
}
Advertisement