Skip to content

Instantly share code, notes, and snippets.

@ourmaninamsterdam
Created April 6, 2022 06:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ourmaninamsterdam/82f03bb33eddad0dd69e34a8b6c696b1 to your computer and use it in GitHub Desktop.
Save ourmaninamsterdam/82f03bb33eddad0dd69e34a8b6c696b1 to your computer and use it in GitHub Desktop.
retryAsync - retry an async function a set amount of times
import retryAsync from '~utils/retryAsync';
describe('retryAsync', () => {
describe('with retry attempts left', () => {
describe('if the async function promise rejects', () => {
it('retries the given async function 3 times before eventually throwing', async () => {
const mockAsyncFn = jest.fn().mockRejectedValue('failed');
await expect(retryAsync(3, () => mockAsyncFn())).rejects.toThrow();
expect(mockAsyncFn).toHaveBeenCalledTimes(3);
});
});
describe('if the async function promise resolves', () => {
it("returns the async function's payload", async () => {
const mockAsyncFn = jest.fn().mockResolvedValue('success');
await expect(retryAsync(3, () => mockAsyncFn())).resolves.toEqual('success');
expect(mockAsyncFn).toHaveBeenCalledTimes(1);
});
});
describe('if the async function fails a couple of times before eventually resolving', () => {
it("returns the async function's payload", async () => {
const mockAsyncFn = jest.fn();
mockAsyncFn.mockRejectedValueOnce('failed1').mockRejectedValueOnce('failed2').mockResolvedValueOnce('success');
await expect(retryAsync(3, () => mockAsyncFn())).resolves.toEqual('success');
expect(mockAsyncFn).toHaveBeenCalledTimes(3);
});
});
});
describe('without retry attempts left', () => {
describe('if the async function rejects', () => {
it('throws', async () => {
const mockAsyncFn = jest.fn().mockRejectedValue('failed');
await expect(retryAsync(3, () => mockAsyncFn())).rejects.toThrow();
expect(mockAsyncFn).toHaveBeenCalledTimes(3);
});
});
});
});
export default async function retryAsync<AsyncFn>(retries: number, asyncFn: () => Promise<AsyncFn>): Promise<AsyncFn> {
try {
retries--;
return await asyncFn();
} catch (err: any) {
if (retries === 0) {
throw new Error(err);
}
return retryAsync(retries, asyncFn);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment