Вот пример кода, который я использую для интеграции selenium WebDriver JS ax для проверки доступности моего веб-сайта:
var AxeBuilder = require('axe-webdriverjs');
var WebDriver = require('selenium-webdriver');
var driver = new WebDriver.Builder()
.forBrowser('firefox')
.build();
driver
.get('https://dequeuniversity.com/demo/mars/')
.then(function() {
AxeBuilder(driver).analyze(function(err, results) {
if (err) {
// Handle error somehow
}
console.info(results);
});
});
Здесь анализируется один URL. Может ли кто-нибудь помочь мне разобрать несколько URL-адресов? Я бы хотел, чтобы результаты всех URL-адресов были напечатаны в качестве входных данных для driver.get (). Любая помощь будет оценена по достоинству!
Поэтому я отформатирую комментарий @ CertainPerformance как ответ.
Самый простой подход - использовать современный синтаксис async/await
:
for (const url of [url1, url2, url3]) {
await driver
.get(url)
.then(async function() {
await AxeBuilder(driver).analyze(function(err, results) {
if (err) {
// Handle error somehow
}
console.info(results);
});
});
}
Не забудьте заменить url1, url2, url3
своими URL-адресами.
P.S. как указано в @ jfriend00 (в комментариях ниже), мы не знаем, действительно ли функция AxeBuilder
возвращает обещание или нет. Так что в последнем случае await
до него (и async
) может оказаться ненужным.
Это не будет ждать завершения AxeBuilder().analyze()
перед переходом к следующей итерации цикла.
@ jfriend00 Пропустил, исправлено!
Я не знаю эту библиотеку, но маловероятно, что .analyze () вернет обещание и получит обратный вызов. Если он не вернет обещание, await не сделает ничего полезного.
@ jfriend00 Ага, постскриптум добавил.
Вы по-прежнему не показываете решение, которое фактически ожидало бы выполнения всех асинхронных операций перед повторением цикла.
@ jfriend00 Я что-то упускаю. Что это за штуки?
Я уже говорил об этом в своем первом комментарии здесь. Подсказка, нужно "промисифицировать" .analyze()
.
указанное выше решение будет работать, но оно будет сериализовано, то есть вы получите результат обещания driver.get
, а затем analyze
результат одного URL-адреса перед переходом к следующему. возможно, вы могли бы использовать promise.all
, чтобы делать все это параллельно. Что-то вроде
function executeGetPromises() {
var getPromises = [];
var drivers = [];
for (const url of [url1, url2, url3]) {
var driver = new WebDriver.Builder().forBrowser('firefox').build();
getPromises.push(driver.get(url));
drivers.push(driver);
}
var analysePromises = [];
int index = 0;
Promise.all(getPromises.map(p => p.catch(e => e)))
.then(results => {
for (int i=0; i< results.length; i++) {
var result = results[i];
if (!(result instanceof Error)) {
analysePromises.push(AxeBuilder(drivers[i]).analyze);
}
}
executeAnalysePromises(analysePromises);
});
}
function executeAnalysePromises (analysePromises) {
Promise.all(analysePromises.map(p => p.catch(e => e)))
.then(results => {
results.forEach(result => {
if (!(result instanceof Error)) {
console.info(result);
}
});
});
}
здесь мы отслеживаем все drivers
, и все обещания driver.get
выполняются параллельно, и как только все getPromises
возвращаются (либо разрешены / отклонены), analysePromises
запускается параллельно.
Обновлено: более простой подход с использованием асинхронных функций. Вышеупомянутое немного сложно, вы можете добиться того же, используя асинхронные функции.
async function executeTask (driver, url) {
try{
await driver.get(url);
let result = await AxeBuilder(driver).analyze();
return Promise.resolve(result);
}
catch(err) {
return Promise.reject(err);
}
}
function iterateThroughUrls(urls) {
urls.forEach(url => {
var driver = new WebDriver.Builder().forBrowser('firefox').build();
executeTask(driver, url).then(result => {
console.info(result);
}).catch(err => {
//handle errors
});
});
}
Привет, Мринал, во-первых, спасибо! Быстрый вопрос: что, если я не хочу, чтобы это работало параллельно и сериализовало этот точный код? Он работает безупречно, единственная проблема в том, что если я даю ему большое количество URL-адресов, он дает сбой. Пожалуйста, помогите!
Используйте Promise.all и сопоставьте массив URL-адресов.
const urlArray = [url1,url2,url3,...];
const finalResult = await Promise.all(urlArray.map(async url=>{
return await driver.get(url);
}))
вы получите весь результат в массиве finalResult
.
await
каждыйPromise
или использоватьPromise.all
?