Gathering detailed insights and metrics for p-retry
Gathering detailed insights and metrics for p-retry
Gathering detailed insights and metrics for p-retry
Gathering detailed insights and metrics for p-retry
npm install p-retry
Typescript
Module System
Min. Node Version
Node Version
NPM Version
99.7
Supply Chain
99.5
Quality
83.3
Maintenance
100
Vulnerability
100
License
JavaScript (97.57%)
TypeScript (2.43%)
Total Downloads
3,372,042,638
Last Day
966,687
Last Week
19,223,002
Last Month
85,870,249
Last Year
829,876,136
MIT License
913 Stars
76 Commits
74 Forks
8 Watchers
1 Branches
23 Contributors
Updated on Sep 02, 2025
Latest Version
7.0.0
Package Id
p-retry@7.0.0
Unpacked Size
19.50 kB
Size
5.80 kB
File Count
5
NPM Version
10.9.2
Node Version
20.19.1
Published on
Aug 21, 2025
Cumulative downloads
Total Downloads
Last Day
-16.5%
966,687
Compared to previous day
Last Week
-1.6%
19,223,002
Compared to previous week
Last Month
3.5%
85,870,249
Compared to previous month
Last Year
17.8%
829,876,136
Compared to previous year
1
Retry a promise-returning or async function
It does exponential backoff and supports custom retry strategies for failed operations.
1npm install p-retry
1import pRetry, {AbortError} from 'p-retry'; 2 3const run = async () => { 4 const response = await fetch('https://sindresorhus.com/unicorn'); 5 6 // Abort retrying if the resource doesn't exist 7 if (response.status === 404) { 8 throw new AbortError(response.statusText); 9 } 10 11 return response.blob(); 12}; 13 14console.log(await pRetry(run, {retries: 5}));
Returns a Promise
that is fulfilled when calling input
returns a fulfilled promise. If calling input
returns a rejected promise, input
is called again until the max retries are reached, it then rejects with the last rejection reason.
Does not retry on most TypeErrors
, with the exception of network errors. This is done on a best case basis as different browsers have different messages to indicate this. See whatwg/fetch#526 (comment)
Type: Function
Receives the number of attempts as the first argument and is expected to return a Promise
or any value.
Type: object
Type: Function
Callback invoked on each retry. Receives a context object containing the error and retry state information.
1import pRetry from 'p-retry'; 2 3const run = async () => { 4 const response = await fetch('https://sindresorhus.com/unicorn'); 5 6 if (!response.ok) { 7 throw new Error(response.statusText); 8 } 9 10 return response.json(); 11}; 12 13const result = await pRetry(run, { 14 onFailedAttempt: ({error, attemptNumber, retriesLeft}) => { 15 console.log(`Attempt ${attemptNumber} failed. There are ${retriesLeft} retries left.`); 16 // 1st request => Attempt 1 failed. There are 5 retries left. 17 // 2nd request => Attempt 2 failed. There are 4 retries left. 18 // … 19 }, 20 retries: 5 21}); 22 23console.log(result);
The onFailedAttempt
function can return a promise. For example, to add a delay:
1import pRetry from 'p-retry'; 2import delay from 'delay'; 3 4const run = async () => { … }; 5 6const result = await pRetry(run, { 7 onFailedAttempt: async () => { 8 console.log('Waiting for 1 second before retrying'); 9 await delay(1000); 10 } 11});
If the onFailedAttempt
function throws, all retries will be aborted and the original promise will reject with the thrown error.
Type: Function
Decide if a retry should occur based on the context. Returning true triggers a retry, false aborts with the error.
It is only called if retries
and maxRetryTime
have not been exhausted.
It is not called for TypeError
(except network errors) and AbortError
.
1import pRetry from 'p-retry'; 2 3const run = async () => { … }; 4 5const result = await pRetry(run, { 6 shouldRetry: ({error, attemptNumber, retriesLeft}) => !(error instanceof CustomError) 7});
In the example above, the operation will be retried unless the error is an instance of CustomError
.
Type: number
Default: 10
The maximum amount of times to retry the operation.
Type: number
Default: 2
The exponential factor to use.
Type: number
Default: 1000
The number of milliseconds before starting the first retry.
Type: number
Default: Infinity
The maximum number of milliseconds between two retries.
Type: boolean
Default: false
Randomizes the timeouts by multiplying with a factor between 1 and 2.
Type: number
Default: Infinity
The maximum time (in milliseconds) that the retried operation is allowed to run.
Type: AbortSignal
You can abort retrying using AbortController
.
1import pRetry from 'p-retry'; 2 3const run = async () => { … }; 4const controller = new AbortController(); 5 6cancelButton.addEventListener('click', () => { 7 controller.abort(new Error('User clicked cancel button')); 8}); 9 10try { 11 await pRetry(run, {signal: controller.signal}); 12} catch (error) { 13 console.log(error.message); 14 //=> 'User clicked cancel button' 15}
Type: boolean
Default: false
Prevents retry timeouts from keeping the process alive.
Only affects platforms with a .unref()
method on timeouts, such as Node.js.
Wrap a function so that each call is automatically retried on failure.
1import {makeRetriable} from 'p-retry'; 2 3const fetchWithRetry = makeRetriable(fetch, {retries: 5}); 4 5const response = await fetchWithRetry('https://sindresorhus.com/unicorn');
Abort retrying and reject the promise.
Type: string
An error message.
Type: Error
A custom error.
You can pass arguments to the function being retried by wrapping it in an inline arrow function:
1import pRetry from 'p-retry'; 2 3const run = async emoji => { 4 // … 5}; 6 7// Without arguments 8await pRetry(run, {retries: 5}); 9 10// With arguments 11await pRetry(() => run('🦄'), {retries: 5});
The package uses setTimeout
and clearTimeout
from the global scope, so you can use the Node.js test timer mocking or a package like sinon
.
Use an AbortController
to signal cancellation on SIGINT, and pass its signal
to pRetry
:
1import pRetry from 'p-retry'; 2 3const controller = new AbortController(); 4 5process.once('SIGINT', () => { 6 controller.abort(new Error('SIGINT received')); 7}); 8 9try { 10 await pRetry(run, {signal: controller.signal}); 11} catch (error) { 12 console.log('Retry stopped due to:', error.message); 13}
The package does not handle process signals itself to avoid global side effects.
No vulnerabilities found.