В автоматизации браузера с помощью Puppeteer работа с сетевыми запросами играет ключевую роль. Одной из фундаментальных концепций является управление очередями запросов, что позволяет эффективно контролировать нагрузку, ускорять тесты и обеспечивать стабильность взаимодействия с веб-страницей.
Puppeteer предоставляет механизм interception для
контроля запросов. С помощью
page.setRequestInterception(true) можно перехватывать
каждый сетевой запрос до его отправки на сервер. Это позволяет:
Пример настройки перехвата запросов:
await page.setRequestInterception(true);
page.on(&
if (request.resourceType() === 'image') {
request.abort(); // Блокировка загрузки изображений
} else {
request.continue(); // Продолжение обычного запроса
}
});
Когда на странице выполняется множество сетевых вызовов, важно контролировать количество одновременных запросов, чтобы не перегрузить тестируемый сервер и не столкнуться с ограничениями браузера. Для этого создаются очереди запросов, которые управляют параллельной обработкой.
Простейшая реализация очереди:
class RequestQueue {
constructor(concurrency = 5) {
this.concurrency = concurrency;
this.queue = [];
this.activeCount = 0;
}
add(task) {
this.queue.push(task);
this.next();
}
next() {
if (this.activeCount >= this.concurrency || this.queue.length === 0) return;
const task = this.queue.shift();
this.activeCount++;
task().finally(() => {
this.activeCount--;
this.next();
});
}
}
Использование:
const queue = new RequestQueue(3); // максимум 3 параллельных запроса
urls.forEach(url => {
queue.add(async () => {
const response = await page.goto(url);
console.log(`${url} загружен с кодом ${response.status()}`);
});
});
Такая модель позволяет регулировать нагрузку и избежать конфликтов при тестировании динамических страниц.
В сложных сценариях тестирования может потребоваться управление приоритетом запросов. Например, критические API-запросы нужно обрабатывать первыми, а вспомогательные ресурсы — позже. Для этого очередь можно расширить с поддержкой приоритетов:
class PriorityQueue extends RequestQueue {
add(task, priority = 0) {
this.queue.push({ task, priority });
this.queue.sort((a, b) => b.priority - a.priority);
this.next();
}
next() {
if (this.activeCount >= this.concurrency || this.queue.length === 0) return;
const { task } = this.queue.shift();
this.activeCount++;
task().finally(() => {
this.activeCount--;
this.next();
});
}
}
Это позволяет тестировать сложные сценарии с предсказуемой последовательностью загрузки ресурсов.
Сетевые запросы часто завершаются ошибкой из-за таймаутов, нестабильного интернета или ограничений сервера. В очередях запросов полезно внедрять механизм повторных попыток:
async function fetchWithRetry(url, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
const response = await page.goto(url);
if (response.ok()) return response;
} catch (e) {
if (i === retries - 1) throw e;
}
}
}
В комбинации с очередями это позволяет повысить надежность тестов и минимизировать сбои из-за временных проблем с сетью.
Для анализа производительности и отладки важно логировать состояние очереди:
queue.add(async () => {
console.log(`Запуск задачи для ${url}`);
await page.goto(url);
console.log(`Завершение задачи для ${url}`);
});
Можно расширить логирование до времени выполнения каждого запроса, состояния очереди и количества активных задач, что помогает выявлять узкие места при нагрузочном тестировании.
Очереди запросов идеально интегрируются с фреймворками типа
Jest, Mocha или Playwright Test, позволяя
контролировать асинхронное поведение в рамках тестов. Через хуки
beforeAll и afterAll можно настраивать
интерцепторы и инициализировать очередь, а внутри it
реализовывать контролируемую загрузку ресурсов.
Эти методы позволяют строить стабильные, предсказуемые и масштабируемые тесты на базе Puppeteer, особенно при работе с динамическими и тяжелыми страницами.