← Усі задачіJavaScript · Senior

runWithLimit: пул промісів

Напишіть функцію runWithLimit(tasks, limit). tasks - масив функцій, кожна повертає проміс. Запустіть їх усі, але так, щоб одночасно виконувалося не більше limit задач: щойно одна закінчується, стартує наступна.

Поверніть проміс із результатами в порядку tasks. Якщо якась задача впала, загальний проміс відхиляється цією помилкою, а нові задачі більше не запускаються.

Тести (6)

  1. let active = 0;
    let peak = 0;
    const task = (v) => async () => { active++; peak = Math.max(peak, active); await wait(20); active--; return v; };
    const result = await runWithLimit([1, 2, 3, 4, 5].map(task), 2);
    expect(result).toEqual([1, 2, 3, 4, 5]);
    expect(peak).toBe(2);
  2. const order = [];
    const task = (v, ms) => async () => { await wait(ms); order.push(v); return v; };
    const result = await runWithLimit([task('a', 60), task('b', 10), task('c', 10)], 2);
    expect(result).toEqual(['a', 'b', 'c']);
    expect(order).toEqual(['b', 'c', 'a']);
  3. expect(await runWithLimit([], 3)).toEqual([]);
  4. const error = new Error('fail');
    await expect(runWithLimit([async () => 1, async () => { throw error; }], 2)).rejects.toBe(error);
  5. const started = fn();
    const tasks = [1, 2, 3].map((v) => () => { started(v); return wait(30).then(() => v); });
    const promise = runWithLimit(tasks, 1);
    await wait(10);
    expect(started).toHaveBeenCalledTimes(1);
    expect(await promise).toEqual([1, 2, 3]);
    expect(started).toHaveBeenCalledTimes(3);
  6. const started = Date.now();
    await runWithLimit([1, 2, 3, 4].map(() => () => wait(40)), 4);
    expect(Date.now() - started < 120).toBe(true);