← Wszystkie zadaniaJavaScript · Senior

retry: ponawianie przy błędzie

Napisz funkcję retry(fn, attempts, delay). Wywołuje ona fn (funkcję, która zwraca obietnicę lub rzuca błąd) i przy błędzie próbuje ponownie, łącznie nie więcej niż attempts razy, czekając delay milisekund między próbami.

Zwróć wynik pierwszej udanej próby. Jeśli wszystkie próby się nie powiodą, odrzuć obietnicę błędem z ostatniej. Synchroniczny wyjątek w fn też liczy się jako nieudana próba.

Testy (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);