Для решения задачи с ограниченным количеством одновременно выполняемых параллельных запросов в JavaScript можно использовать асинхронные функции и Promise. Мы можем создать очередь из промисов, чтобы управлять выполнением 3 параллельных запросов.
Вот пример кода, который демонстрирует, как это можно реализовать:
```javascript
async function performRequest(id) {
// Имитация асинхронного запроса (например, fetch).
return new Promise((resolve) => {
setTimeout(() => {
console.log(`Запрос ${id} выполнен`);
resolve(`Результат запроса ${id}`);
}, Math.random() * 2000); // Задержка от 0 до 2 секунд.
});
}
async function limitConcurrentRequests(requests, limit) {
const results = [];
const executing = [];
for (let i = 0; i < requests.length; i++) {
const request = requests[i];
const p = performRequest(request).then(result => {
results[i] = result; // Сохранение результата по индексу
});
executing.push(p);
if (executing.length >= limit) {
// Ждем завершения любого запроса
await Promise.race(executing);
// Убираем завершившийся запрос из executing
executing.splice(executing.findIndex(p => p === Promise.race(executing)), 1);
}
}
// Ждем завершения оставшихся запросов
await Promise.all(executing);
return results;
}
// Пример использования
const requests = Array.from({ length: 10 }, (_, i) => i + 1); // Массив запросов с id от 1 до 10
limitConcurrentRequests(requests, 3).then(results => {
console.log('Все запросы завершены:', results);
});
```
### Объяснение кода:
1. **Функция `performRequest(id)`**: Это функция, которая имитирует асинхронный запрос (например, к API). Здесь используется `setTimeout`, чтобы создать случайную задержку выполнения.
2. **Функция `limitConcurrentRequests(requests, limit)`**:
- `requests`: массив идентификаторов запросов.
- `limit`: максимальное количество параллельных запросов.
- В этой функции мы создаем массив `results` для хранения результатов и массив `executing` для отслеживания текущих выполняемых запросов.
3. **Цикл `for`**:
- Для каждого запроса создается промис `p`, который выполняет `performRequest`.
- Мы добавляем этот промис в массив `executing`.
- Если количество выполняющихся промисов достигает лимита, мы ждем завершения любого из них с помощью `Promise.race()`, а затем удаляем его из массива `executing`.
4. **`Promise.all(executing)` после цикла**: После завершения цикла мы ждем окончания всех оставшихся промисов в массиве `executing`.
5. **Итог**: После завершения всех операций мы выводим результаты.
Такой подход позволяет управлять количеством одновременно выполняемых запросов, при этом результаты сохраняются и выводятся в финале.