Функция runWithLimit реализует параллельное выполнение асинхронных запросов с ограничением на максимальное количество одновременно выполняемых запросов (limit).
* Реализуйте функцию, которая выполнит callback с данными
Функция runWithLimit реализует параллельное выполнение асинхронных запросов с ограничением на максимальное количество одновременно выполняемых запросов (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[]> { // НАЧАЛО РЕШЕНИЯ if (limit < 1 || data.length === 0) { return Promise.resolve([]); }
if (limit >= data.length) { return Promise.all(data.map(callback)); }
const result: Response[] = new Array(data.length); let index = 0;
const run = async () => { if (index >= data.length) return;
const elem = data[index];
try {
result[index] = await callback(elem);
} catch (err) {
result[index] = (err) as Response; // todo: обработать ошибку
}
index++;
run();
};
const startPack = Array.from({ length: limit }, run); await Promise.all(startPack);
return result; }
Ответ
Функция runWithLimit реализует параллельное выполнение асинхронных запросов с ограничением на максимальное количество одновременно выполняемых запросов (limit).
Основная идея решения:
- Если лимит больше или равен количеству запросов, запускаем все сразу через
Promise.all. - Иначе запускаем ровно
limitпараллельных задач. - Каждая задача после завершения запускает следующую из очереди, пока не обработает все данные.
Это позволяет эффективно использовать параллелизм, не превышая заданный лимит.
Пример:
const results = await runWithLimit({
callback: async (url: string) => {
const response = await fetch(url);
return response.json();
},
data: ['url1', 'url2', 'url3', 'url4'],
limit: 2,
});
console.log(results);
Таким образом, одновременно будут выполняться не более 2 запросов, что помогает контролировать нагрузку.