Параллельный запуск запросов с ограничением количества

Запустите не больше limit работников с общим индексом. Каждый берёт следующую задачу только после завершения предыдущей и записывает результат на исходную позицию.

Короткий ответ

Что ответить на собеседовании

Запустите не больше limit работников с общим индексом. Каждый берёт следующую задачу только после завершения предыдущей и записывает результат на исходную позицию.

Подробный разбор

Ответ с пояснениями

Условие

Создайте функцию, которая для каждого элемента входного массива вызывает переданный callback и собирает результаты в массив ответов Response[].

Выполнение запросов должно происходить одновременно, однако количество одновременно запущенных запросов ограничено параметром limit. Такая схема позволяет уменьшить общее время работы программы, не перегружая ресурсы.

type Props<RequestData, Response> = {
    callback: (args: RequestData) => Promise<Response>;
    data: Array<RequestData>;
    limit: number;
};

/*                    Решение задачи                */
export async function runWithLimit<RequestData, Response>({
    callback,
    data,
    limit,
}: Props<RequestData, Response>): Promise<Response[]> {
    /*    START SOLUTION HERE  */
    const result: Response[] = [];

    return Promise.all([]);
}

Ответ

Запустите не больше limit работников с общим индексом. Каждый берёт следующую задачу только после завершения предыдущей и записывает результат на исходную позицию.

export async function runWithLimit<RequestData, Response>({ callback, data, limit }: Props<RequestData, Response>): Promise<Response[]> {
  if (!Number.isInteger(limit) || limit < 1) throw new RangeError('limit must be positive');
  const result: Response[] = new Array(data.length);
  let next = 0, failed = false;
  async function worker() {
    while (!failed) {
      const index = next++;
      if (index >= data.length) return;
      try { result[index] = await callback(data[index]); }
      catch (error) { failed = true; throw error; }
    }
  }
  await Promise.all(Array.from({ length: Math.min(limit, data.length) }, () => worker()));
  return result;
}

В JavaScript получение индекса выполняется синхронно до await, поэтому работники не берут один элемент дважды. После первой ошибки новые задания не запускаются, но уже выполняющиеся не отменяются автоматически. Пустой вход возвращает [], порядок результатов не зависит от скорости запросов.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее