retry-retry
v1.0.0
Published
Javascript library for easy retrying of promise based tasks.
Downloads
3
Maintainers
Readme
retry-retry ·
Javascript library for easy retrying of tasks (task is just a function).
Simple example (polling for a resource) using async/await:
const retry = require('retry-retry')
const resource = await retry(async (_retry) => {
try {
return await yourResourceFetchingPromiseReturningFunction()
} catch (e) {
if (e.code == 'ResourceNotReady') _retry() else throw 'Unexpected error, stopping.'
}
}, { pauseMs: 1000, maxTotalTimeMs: 3 * 60 * 1000, retryStrategy: 'exponential' })
Features
- Promise based.
- Supports setting limit on total elapsed time and / or max number of tries.
- Supports linear, exponential or custom retry strategy (duration of pauses between tries).
- No dependencies.
- Simple interface.
- Has fun name.
Using in your project
retry-retry is available on npm, so just install it with
npm install -S retry-retry
There is only one main function, retry
, which you can import in your code with
const retry = require('./retry-retry')
or with
import { retry } from 'retry-retry'
TODO: or is it import retry from 'retry-retry'
?
Usage and examples
retry-retry has only one public function: retry
.
In order to run your function many times, you just pass it to retry
and then have it signal
that it succeeded / wants to try again / is giving up.
You can also pass additional options to retry
for finer control of how retrying is done.
That is it! Check examples below and API for more details.
Example: Dice throwing
Let's define function throwDice
, that randomly returns integer between 1 and 6:
const throwDice = () => Math.floor(Math.random() * 6) + 1)
We want to throw dice until we get 5 or 6. If we get 1 we get discouraged and give up. Let's define the task.
const throwDiceTask = async (_retry) => {
const number = throwDice()
if (number == 5 || number == 6) return number // If success, we return the number we got.
else if (number == 1) throw 'I got 1 :(.' // We give up.
else _retry() // By calling _retry() we signalize that we want to try again after this try.
}
Now we call it with retry()
and that is it! It will repeat the task forever, until we get 5, 6
or 1.
const number = await retry(throwDiceTask)
Right now, task is retried immediatelly after the previous try finished, meaning that we are repeatedly throwing the dice with no pause. That is making us really tired and we also want to look more elegant while throwing the dice, so let's take a pause of 1 second after each throw.
const number = await retry(throwDiceTask, { pauseMs: 1000 })
Throwing dice like a robot, with always the same pause, soon becomes boring, so we decide to liven it up a bit by taking random pauses between 1 and 5 seconds with every 50th pause being 10 min so we can take a short nap.
const ourRetryStrategy = (numTries) => {
if (numTries % 50 == 0) return 10 * 60 * 1000
return (Math.random() * 4 + 1) * 1000
}
const number = await retry(throwDiceTask, { retryStrategy: ourRetryStrategy })
We know that in theory it is possible that we don't get 1, 5 or 6 for very long time (never) and we have other stuff to do than throw dice whole day, so we need some stop conditions. Let's say that we are not going to be throwing dice for more than 3 hours or 1000 throws, whichever happens first, and in that case we want to reject the promise with our custom message.
const number = await retry(throwDiceTask, {
retryStrategy: ourRetryStrategy,
maxTries: 1000,
maxTotalTimeMs: 3 * 60 * 60 * 1000,
errorOnLimit: 'I am giving up!'
})
That is it! We are ready to throw the dice and have some fun while doing it without the risk of it taking over our whole day.
API
TODO
FAQ
Q: Where did the name retry-retry
come from?
A: First of all, retry
was already taken :D.
Second, it should be a (f/p)unny name because it repeats / "retries" word "retry" two times.
Finally, if you pass retry()
an arrow function like this retry(_retry => ...)
it looks
like retry-retry
. I actually didn't notice this until after I already chose the name,
but it makes a good story :D.