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

retry: повтор у разі помилки

Напишіть функцію retry(fn, attempts, delay). Вона викликає fn (функцію, яка повертає проміс або кидає помилку) і в разі помилки пробує знову, загалом не більше attempts разів, чекаючи delay мілісекунд між спробами.

Поверніть результат першої успішної спроби. Якщо всі спроби невдалі, відхиліть проміс помилкою останньої спроби. Синхронна помилка всередині fn теж вважається невдалою спробою.

Тести (5)

  1. const f = fn(async () => 'ok');
    expect(await retry(f, 3, 10)).toBe('ok');
    expect(f).toHaveBeenCalledTimes(1);
  2. let n = 0;
    const f = fn(async () => { n++; if (n < 3) throw new Error('fail ' + n); return n; });
    expect(await retry(f, 5, 10)).toBe(3);
    expect(f).toHaveBeenCalledTimes(3);
  3. const f = fn(async () => { throw new Error('nope ' + f.calls.length); });
    await expect(retry(f, 3, 5)).rejects.toThrow('nope 3');
    expect(f).toHaveBeenCalledTimes(3);
  4. const f = fn(() => { throw new Error('sync'); });
    await expect(retry(f, 2, 5)).rejects.toThrow('sync');
    expect(f).toHaveBeenCalledTimes(2);
  5. let n = 0;
    const f = async () => { n++; if (n === 1) throw new Error('x'); return 'done'; };
    const started = Date.now();
    expect(await retry(f, 2, 60)).toBe('done');
    expect(Date.now() - started >= 50).toBe(true);