Skip to content

Commit 1a81c1e

Browse files
committed
Add makeRetriable method
Fixes #61
1 parent 4811051 commit 1a81c1e

4 files changed

Lines changed: 63 additions & 1 deletion

File tree

index.d.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,3 +195,20 @@ export default function pRetry<T>(
195195
input: (attemptCount: number) => PromiseLike<T> | T,
196196
options?: Options
197197
): Promise<T>;
198+
199+
/**
200+
Wrap a function so that each call is automatically retried on failure.
201+
202+
@example
203+
```
204+
import {makeRetriable} from 'p-retry';
205+
206+
const fetchWithRetry = makeRetriable(fetch, {retries: 5});
207+
208+
const response = await fetchWithRetry('https://sindresorhus.com/unicorn');
209+
```
210+
*/
211+
export function makeRetriable<Arguments extends readonly unknown[], Result>(
212+
function_: (...arguments_: Arguments) => PromiseLike<Result> | Result,
213+
options?: Options
214+
): (...arguments_: Arguments) => Promise<Result>;

index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,7 @@ export default async function pRetry(input, options = {}) {
135135
// Should not reach here, but in case it does, throw an error
136136
throw new Error('Retry attempts exhausted without throwing an error.');
137137
}
138+
139+
export function makeRetriable(function_, options) {
140+
return (...arguments_) => pRetry(() => function_(...arguments_), options);
141+
}

readme.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,18 @@ Prevents retry timeouts from keeping the process alive.
193193

194194
Only affects platforms with a `.unref()` method on timeouts, such as Node.js.
195195

196+
### makeRetriable(function, options?)
197+
198+
Wrap a function so that each call is automatically retried on failure.
199+
200+
```js
201+
import {makeRetriable} from 'p-retry';
202+
203+
const fetchWithRetry = makeRetriable(fetch, {retries: 5});
204+
205+
const response = await fetchWithRetry('https://sindresorhus.com/unicorn');
206+
```
207+
196208
### AbortError(message)
197209
### AbortError(error)
198210

test.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import path from 'node:path';
44
import {execa} from 'execa';
55
import test from 'ava';
66
import delay from 'delay';
7-
import pRetry, {AbortError} from './index.js';
7+
import pRetry, {makeRetriable, AbortError} from './index.js';
88

99
const fixture = Symbol('fixture');
1010
const fixtureError = new Error('fixture');
@@ -697,3 +697,32 @@ main();
697697
await fs.unlink(temporaryFile);
698698
}
699699
});
700+
701+
test('makeRetriable wraps and retries the function', async t => {
702+
let callCount = 0;
703+
const function_ = async (a, b) => {
704+
callCount++;
705+
if (callCount < 3) {
706+
throw new Error('fail');
707+
}
708+
709+
return a + b;
710+
};
711+
712+
const retried = makeRetriable(function_, {retries: 5, minTimeout: 0});
713+
const result = await retried(2, 3);
714+
t.is(result, 5);
715+
t.is(callCount, 3);
716+
});
717+
718+
test('makeRetriable passes arguments and options', async t => {
719+
let lastArguments;
720+
const function_ = (...arguments_) => {
721+
lastArguments = arguments_;
722+
throw new Error('fail');
723+
};
724+
725+
const retried = makeRetriable(function_, {retries: 1, minTimeout: 0});
726+
await t.throwsAsync(() => retried('foo', 42));
727+
t.deepEqual(lastArguments, ['foo', 42]);
728+
});

0 commit comments

Comments
 (0)