#javascript #node.js #asynchronous #promise
#javascript #node.js #асинхронный #обещание
Вопрос:
Я создал функцию, которая запрашивает у пользователя 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.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);
}
};
Комментарии:
1. установка какой переменной в getURL (ах)?
2. переменная установлена как url
3. Это
else if ('No' || 'no' || 'NO') {
просто неправильное условие. Возможно, вы имеете в видуelse if (url.toLowerCase() === 'no') {
?4. И,
return Promise.resolve().then((resolve, reject) =>
должно бытьreturn new Promise((resolve, reject) =>
.Promise.resolve()
возвращает разрешенное обещание, которое вы можете вызвать.then()
, но оно НЕ передает два аргумента.then()
обработчику. Вместо этого вам нужно использоватьnew Promise()
конструктор.5. Пожалуйста, НЕ редактируйте исправления, о которых идет речь. Это меняет весь ваш вопрос и делает недействительными ответы, которые вам уже дали люди.
Ответ №1:
Я думаю, что это вопрос синтаксиса. Здесь я переключил исходную строку, чтобы правильно использовать конструктор 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);
}
});
});
};
Редактировать: добавление версии async / await. В принципе, я думаю, вам никогда не придется отклонять. Я отредактировал приведенное выше, чтобы также не отклонять. Также я предполагаю 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.log('Please type in a valid URL or type "no" to use base url.')
return requestSiteURL()
}
}
Комментарии:
1. итак, я внес это изменение, и оно запрашивает меня из другой функции, но никогда не проходит через условные операторы. Если я напишу «картофель», он все равно примет это
2. возможно, проверьте
validUrl.isUri
. Это единственное другое условие, которое я вижу, кроме правильного.3. итак, если я напишу действительный URL-адрес с этим, я получу правильный вывод, но в противном случае я получаю сообщение об ошибке, что у меня есть необработанное promiserejectionwarning
4. Добавлена версия async / await, также первая перестала отклоняться при ближайшем рассмотрении.
5. это сработало, я также поместил свой URL-адрес по умолчанию в свою функцию, чтобы он не был глобальным. Большое вам спасибо!!!!
Ответ №2:
На первый взгляд не похоже, что ваше условие «else» вообще будет ждать. Вы отклоняете обещание и рекурсивно вызываете requestSiteURL()
, но ничего не делаете с возвращенным обещанием. Это снова задаст вопрос, но вызывающая функция не имеет возможности получить доступ к этому обещанию. Исходное обещание, которое было возвращено, уже отклонено. Новое обещание нигде не упоминается, поэтому, когда resolve или reject вызывается во второй раз, нет кода для доступа к результату.
Если вы хотите, чтобы ваш код потерпел неудачу и отклонил возвращенное обещание, тогда вам не следует вызывать его снова в операторе else .
Если вы хотите, чтобы функция one продолжала задавать вопрос до тех пор, пока не будет введен правильный ответ, вы можете исправить эту проблему, инкапсулировав свой код в функцию и продолжая вызывать ее при ошибке, пока она не разрешится с помощью исходного параметра «разрешить» возвращаемого вами обещания. Это не похоже на readline.вопрос () принимает асинхронную функцию либо:
// 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.log(
'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();
});
};
Комментарии:
1. добавленный мной код не включает весь мой скрипт, я могу включить его, он просто очень длинный.