Как использовать async/await, чтобы получить ввод от пользователя, но подождать, пока весь оператор условия не будет прочитан перед разрешением?

Я создал функцию, которая запрашивает у пользователя URL-адрес, а затем проверяет, что введенный ввод действительно является URL-адресом. Проблема в том, что когда я вызываю эту функцию из моей другой функции, я смог заставить ее ждать ввода пользователя раньше, но она не проходит через весь оператор условия перед возвратом URL-адреса.

Как мне использовать promises/async/await, чтобы дождаться, пока моя функция requestSiteURL() завершит выполнение своего оператора условия, прежде чем устанавливать переменную в 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.info(
            '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);
  }
};

установка какой переменной в getURL(S)?

richytong 12.12.2020 00:52

набор переменных - это URL

kayvera 12.12.2020 00:53

Это else if ('No' || 'no' || 'NO') { просто неправильное условное выражение. Возможно, вы имели в виду else if (url.toLowerCase() === 'no') {?

jfriend00 12.12.2020 01:04

И return Promise.resolve().then((resolve, reject) => должно быть return new Promise((resolve, reject) => . Promise.resolve() возвращает разрешенное обещание, которое вы можете вызвать .then(), но НЕ передает два аргумента обработчику .then(). Вместо этого вам нужно использовать конструктор new Promise().

jfriend00 12.12.2020 01:06

Пожалуйста, НЕ редактируйте исправления в вопросе. Это меняет весь ваш вопрос и делает недействительными ответы, которые вам уже дали люди.

jfriend00 12.12.2020 01:08

о, ладно, извините, не знал

kayvera 12.12.2020 01:09

Что именно является условием отказа? Он сразу возвращается каждый раз или только после ввода неправильного URL-адреса?

Jason Goemaat 12.12.2020 01:11

поэтому с ответом Richytong, если я ввожу что-то вроде «po», я получаю «предупреждение об отклонении необработанного обещания»

kayvera 12.12.2020 01:13

Потому что у вас нет обработчика отклоненного обещания от let url = await requestSiteURL();. Поставьте try/catch вокруг этого. И ваше else if условие неверно. И вы решаете с пустым URL-адресом, но никогда не проверяете это в вызывающем объекте. Этот код нуждается в большом количестве исправлений.

jfriend00 12.12.2020 01:17

Я изменил выражение else if и не включил весь код, у меня есть baseurl, у которого уже есть URL-адрес. Извините, мой настоящий сценарий длинный, поэтому я не включил его полностью, а только часть, которая не работает. Я попытался обернуть let url = await requestSiteURL(), но получил ту же ошибку, такую ​​же, если я поместил ее в обещание

kayvera 12.12.2020 01:25
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
10
1 722
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я думаю, что это вопрос синтаксиса. Здесь я переключил исходную строку, чтобы правильно использовать конструктор Promise. Обещание мдн

// 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.info(
          'Please type in a valid URL or type "no" to use base url.'
        )
        requestSiteURL().then(resolve);
      }
    });
  });
};

Обновлено: добавление асинхронной/ожидающей версии. В принципе, я думаю, вам никогда не придется отказываться. Я отредактировал приведенное выше, чтобы не отклонять. Также я предполагаю, что URL является URL-адресом по умолчанию (это конфликтует с глобальным пространством имен URL, просто для записи)

// 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.info('Please type in a valid URL or type "no" to use base url.')
    return requestSiteURL()
  }
}

поэтому я сделал это изменение, и оно предлагает мне другую функцию, но никогда не проходит через условные операторы. Если я напишу «картофель», он все равно примет это

kayvera 12.12.2020 01:08

возможно проверю validUrl.isUri. Это единственное другое условие, которое я вижу, кроме правильного.

richytong 12.12.2020 01:10

поэтому, если я напишу действительный URL-адрес с этим, я получу правильный вывод, но в противном случае я получаю сообщение об ошибке, что у меня есть необработанное предупреждение об отказе от обещания.

kayvera 12.12.2020 01:17

Добавлена ​​асинхронная/ожидающая версия, первая из которых перестала отклоняться при ближайшем рассмотрении.

richytong 12.12.2020 01:35

это сработало, я также поместил свой URL-адрес по умолчанию в свою функцию, чтобы он не был глобальным. Большое спасибо!!!!

kayvera 12.12.2020 01:47

На первый взгляд не похоже, что ваше «еще» условие вообще не будет ждать. Вы отклоняете промис и рекурсивно вызываете requestSiteURL(), но ничего не делаете с возвращенным промисом. Это задаст вопрос снова, но вызывающая функция не сможет получить доступ к этому обещанию. Первоначальное обещание, которое было возвращено, уже отклонено. Новое обещание нигде не упоминается, поэтому при повторном вызове разрешения или отклонения нет кода для доступа к результату.

Если вы хотите, чтобы ваш код потерпел неудачу и отклонил возвращенное обещание, вам не следует снова вызывать его в операторе else.

Если вы хотите, чтобы одна функция продолжала задавать вопрос до тех пор, пока не будет введен действительный ответ, вы можете исправить эту проблему, инкапсулировав свой код в функцию и продолжая вызывать ее при ошибке до тех пор, пока она не разрешится с исходным параметром «разрешить» обещай, что вернешься. Не похоже, что readline.question() также использует асинхронную функцию:

// request url from user in command prompt
const requestSiteURL = () => {
  return new Promise((resolve, reject) => {
    const askQuestion = () => {
      readline.question('Please type url: ', (url) => {
        if (validUrl.isUri(url)) {
          readline.close(); // close readline here?
          resolve(url);
        } else if ('No' || 'no' || 'NO') {
          url = URL;
          // don't close readline here?
          resolve(url);
        } else {
          console.info(
            'Please type in a valid URL or type "no" to use base url.'
          );
          // call askQuestion() again until we resolve with something
          askQuestion()
        }
      });
      
      // call askQuestion() the first time
      askQuestion();
  });
};

код, который я добавил, не включает весь мой скрипт, я могу его включить, он просто очень длинный.

kayvera 12.12.2020 01:18

Другие вопросы по теме