Я создал функцию, которая запрашивает у пользователя 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);
}
};
набор переменных - это URL
Это else if ('No' || 'no' || 'NO') {
просто неправильное условное выражение. Возможно, вы имели в виду else if (url.toLowerCase() === 'no') {
?
И return Promise.resolve().then((resolve, reject) =>
должно быть return new Promise((resolve, reject) =>
. Promise.resolve()
возвращает разрешенное обещание, которое вы можете вызвать .then()
, но НЕ передает два аргумента обработчику .then()
. Вместо этого вам нужно использовать конструктор new Promise()
.
Пожалуйста, НЕ редактируйте исправления в вопросе. Это меняет весь ваш вопрос и делает недействительными ответы, которые вам уже дали люди.
о, ладно, извините, не знал
Что именно является условием отказа? Он сразу возвращается каждый раз или только после ввода неправильного URL-адреса?
поэтому с ответом Richytong, если я ввожу что-то вроде «po», я получаю «предупреждение об отклонении необработанного обещания»
Потому что у вас нет обработчика отклоненного обещания от let url = await requestSiteURL();
. Поставьте try/catch
вокруг этого. И ваше else if
условие неверно. И вы решаете с пустым URL-адресом, но никогда не проверяете это в вызывающем объекте. Этот код нуждается в большом количестве исправлений.
Я изменил выражение else if и не включил весь код, у меня есть baseurl, у которого уже есть URL-адрес. Извините, мой настоящий сценарий длинный, поэтому я не включил его полностью, а только часть, которая не работает. Я попытался обернуть let url = await requestSiteURL(), но получил ту же ошибку, такую же, если я поместил ее в обещание
Я думаю, что это вопрос синтаксиса. Здесь я переключил исходную строку, чтобы правильно использовать конструктор 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()
}
}
поэтому я сделал это изменение, и оно предлагает мне другую функцию, но никогда не проходит через условные операторы. Если я напишу «картофель», он все равно примет это
возможно проверю validUrl.isUri
. Это единственное другое условие, которое я вижу, кроме правильного.
поэтому, если я напишу действительный URL-адрес с этим, я получу правильный вывод, но в противном случае я получаю сообщение об ошибке, что у меня есть необработанное предупреждение об отказе от обещания.
Добавлена асинхронная/ожидающая версия, первая из которых перестала отклоняться при ближайшем рассмотрении.
это сработало, я также поместил свой URL-адрес по умолчанию в свою функцию, чтобы он не был глобальным. Большое спасибо!!!!
На первый взгляд не похоже, что ваше «еще» условие вообще не будет ждать. Вы отклоняете промис и рекурсивно вызываете 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();
});
};
код, который я добавил, не включает весь мой скрипт, я могу его включить, он просто очень длинный.
установка какой переменной в getURL(S)?