Skip to content

Commit b993a96

Browse files
pukubasindresorhus
andauthored
Add shouldRetry option (#75)
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
1 parent 4f5ec69 commit b993a96

File tree

4 files changed

+76
-1
lines changed

4 files changed

+76
-1
lines changed

index.d.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,28 @@ export type Options = {
4141
*/
4242
readonly onFailedAttempt?: (error: FailedAttemptError) => void | Promise<void>;
4343

44+
/**
45+
Decide if a retry should occur based on the error. Returning true triggers a retry, false aborts with the error.
46+
47+
It is not called for `TypeError` (except network errors) and `AbortError`.
48+
49+
@param error - The error thrown by the input function.
50+
51+
@example
52+
```
53+
import pRetry from 'p-retry';
54+
55+
const run = async () => { … };
56+
57+
const result = await pRetry(run, {
58+
shouldRetry: error => !(error instanceof CustomError);
59+
});
60+
```
61+
62+
In the example above, the operation will be retried unless the error is an instance of `CustomError`.
63+
*/
64+
readonly shouldRetry?: (error: FailedAttemptError) => boolean | Promise<boolean>;
65+
4466
/**
4567
You can abort retrying using [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController).
4668

index.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export default async function pRetry(input, options) {
3232
options = {
3333
onFailedAttempt() {},
3434
retries: 10,
35+
shouldRetry: () => true,
3536
...options,
3637
};
3738

@@ -70,7 +71,14 @@ export default async function pRetry(input, options) {
7071
throw error;
7172
}
7273

73-
await options.onFailedAttempt(decorateErrorWithCounts(error, attemptNumber, options));
74+
decorateErrorWithCounts(error, attemptNumber, options);
75+
76+
if (!(await options.shouldRetry(error))) {
77+
operation.stop();
78+
reject(error);
79+
}
80+
81+
await options.onFailedAttempt(error);
7482

7583
if (!operation.retry(error)) {
7684
throw operation.mainError();

readme.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,26 @@ const result = await pRetry(run, {
9999

100100
If the `onFailedAttempt` function throws, all retries will be aborted and the original promise will reject with the thrown error.
101101

102+
##### shouldRetry(error)
103+
104+
Type: `Function`
105+
106+
Decide if a retry should occur based on the error. Returning true triggers a retry, false aborts with the error.
107+
108+
It is not called for `TypeError` (except network errors) and `AbortError`.
109+
110+
```js
111+
import pRetry from 'p-retry';
112+
113+
const run = async () => { … };
114+
115+
const result = await pRetry(run, {
116+
shouldRetry: error => !(error instanceof CustomError);
117+
});
118+
```
119+
120+
In the example above, the operation will be retried unless the error is an instance of `CustomError`.
121+
102122
##### signal
103123

104124
Type: [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal)

test.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,3 +277,28 @@ test('preserves the abort reason', async t => {
277277

278278
t.is(index, 3);
279279
});
280+
281+
test('should retry only when shouldRetry returns true', async t => {
282+
t.plan(2);
283+
284+
const shouldRetryError = new Error('should-retry');
285+
const customError = new Error('custom-error');
286+
287+
let index = 0;
288+
289+
await t.throwsAsync(pRetry(async () => {
290+
await delay(40);
291+
index++;
292+
const error = index < 3 ? shouldRetryError : customError;
293+
throw error;
294+
}, {
295+
async shouldRetry(error) {
296+
return error.message === shouldRetryError.message;
297+
},
298+
retries: 10,
299+
}), {
300+
is: customError,
301+
});
302+
303+
t.is(index, 3);
304+
});

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy