← Назад ко всем вопросам

Как бы ты реализовал ограничение числа параллельных запросов (например, не более N одновременных запросов к API)?

1️⃣ Как кратко ответить

Для ограничения числа параллельных запросов к API можно использовать очередь запросов и семафор. Семафор контролирует количество одновременно выполняемых запросов, а очередь хранит оставшиеся запросы, которые будут выполнены по мере освобождения семафора.

2️⃣ Подробное объяснение темы

Ограничение числа параллельных запросов необходимо для предотвращения перегрузки сервера и обеспечения стабильной работы приложения. Это особенно важно при работе с API, где сервер может иметь ограничения на количество одновременных соединений.

Пример реализации

Рассмотрим реализацию на JavaScript с использованием промисов и семафора. Мы создадим функцию, которая будет управлять очередью запросов и ограничивать их количество.

class RequestQueue {
  constructor(maxConcurrent) {
    this.maxConcurrent = maxConcurrent; // Максимальное количество параллельных запросов
    this.currentConcurrent = 0; // Текущее количество выполняемых запросов
    this.queue = []; // Очередь запросов
  }
​
  // Метод для добавления запроса в очередь
  addRequest(requestFunction) {
    return new Promise((resolve, reject) => {
      const executeRequest = () => {
        this.currentConcurrent++; // Увеличиваем счетчик выполняемых запросов
​
        // Выполняем запрос
        requestFunction()
          .then(resolve)
          .catch(reject)
          .finally(() => {
            this.currentConcurrent--; // Уменьшаем счетчик после завершения запроса
            this.next(); // Пытаемся выполнить следующий запрос из очереди
          });
      };
​
      // Если количество выполняемых запросов меньше максимального, выполняем запрос сразу
      if (this.currentConcurrent < this.maxConcurrent) {
        executeRequest();
      } else {
        // Иначе добавляем запрос в очередь
        this.queue.push(executeRequest);
      }
    });
  }
​
  // Метод для выполнения следующего запроса из очереди
  next() {
    if (this.queue.length > 0 && this.currentConcurrent < this.maxConcurrent) {
      const nextRequest = this.queue.shift(); // Извлекаем следующий запрос из очереди
      nextRequest(); // Выполняем его
    }
  }
}
​
// Пример использования
const apiRequest = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log('Request completed');
      resolve();
    }, 1000); // Симуляция запроса с задержкой
  });
};
​
const requestQueue = new RequestQueue(3); // Создаем очередь с ограничением в 3 параллельных запроса
​
// Добавляем запросы в очередь
for (let i = 0; i < 10; i++) {
  requestQueue.addRequest(apiRequest);
}

Объяснение кода

  1. Класс RequestQueue: Управляет очередью запросов и ограничивает количество параллельных запросов.

    • maxConcurrent: Максимальное количество параллельных запросов.
    • currentConcurrent: Текущее количество выполняемых запросов.
    • queue: Массив для хранения запросов, которые ожидают выполнения.
  2. Метод addRequest: Добавляет новый запрос в очередь.

    • Создает промис, который будет разрешен или отклонен в зависимости от результата выполнения запроса.
    • Если текущее количество выполняемых запросов меньше максимального, запрос выполняется сразу.
    • Иначе запрос добавляется в очередь.
  3. Метод next: Выполняет следующий запрос из очереди, если это возможно.

    • Проверяет, есть ли запросы в очереди и можно ли выполнить еще один запрос.
    • Извлекает и выполняет следующий запрос из очереди.
  4. Пример использования: Создается очередь с ограничением в 3 параллельных запроса. В очередь добавляется 10 запросов, каждый из которых симулирует выполнение с задержкой в 1 секунду.

Этот подход позволяет эффективно управлять количеством параллельных запросов, предотвращая перегрузку сервера и обеспечивая стабильную работу приложения.

Тема: JavaScript
Стадия: Tech

🔒 Подпишись на бусти автора и стань Алигатором, чтобы получить полный доступ к функционалу сайта и отслеживать свой прогресс!

Твои заметки