npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

sisyphus-retry

v0.2.0

Published

Lightweight library for retrying asynchronous tasks with fluent API

Readme

sisyphus-retry

npm npm bundle size (minified + gzip) GitHub

Lightweight library for retrying asynchronous tasks with fluent API.

Based on this reddit comment.

Installation

Formats

sisyphus-retry distributes in a number of formats.

| | Format | Minified? | Main use case | | --------------------------------- | -------------------- |:------------------:| -------------- | | source | ES2015 module | :x: | Bundler | | es | ES2015 module | :heavy_check_mark: | Modern browser | | cjs | CommonJS | :heavy_check_mark: | Node | | global | Global var export | :heavy_check_mark: | Browser |

Source

For being built by a ES2015-aware bundler since those work better using unminfied source. A bundler that respects the "module" package.json field (e.g. Webpack 2+, rollup) will use this distributable.

ES2015 module

Minified ES2015 module. This is for importing in the modern browsers that support <script type=module>. See the Broswer section.

CommonJS

Mainly for require from NodeJS, which uses this distributable because of the package.json "main" field.

Global variable export

This exports to the sisyphus global variable. Mainly for being used from a broswer via <script>.

npm

$ npm install sisyphus-retry
# or
$ yarn add sisyphus-retry
# or
$ pnpm install sisyphus-retry

The npm package includes all formats

Modern browsers

If you only target modern browsers that support ES2015 modules.

<script type="module">
import sisyphus from '//unpkg.com/sisyphus-retry/dist/sisyphus.es.js'
// Your code
</script>

<!-- or, for a specific version -->

<script type="module">
import sisyphus from '//unpkg.com/[email protected]/dist/sisyphus.es.js'
// Your code
</script>

Browsers

If you target browsers that don't support ES2015 modules, either use the global variable bundle

<script src="//unpkg.com/sisyphus-retry"></script>
<!-- or, for a specific version -->
<script src="//unpkg.com/[email protected]"></script>

or use a fallback

<script type="module">
import sisyphus from '//unpkg.com/sisyphus-retry/dist/sisyphus.es.js'
window.sisyphus = sisyphus
</script>
<script src="//unpkg.com/sisyphus-retry" nomodule></script>
<script>
// Now sisyphus is defined as a global
</script>

Like above, you can use a specific version by adding specifiers

Usage

Example

import sisyphus from 'sisyphus-retry'
import exponentially from 'sisyphus-retry/dist/wait/exponentially.es.js'

// A task that never succeeds
const pushBoulder = () =>
	Promise.reject(new Error("Boulder rolls down again!"))

// A network request using axios
const fetchData = () => axios.get('/url/to/data')

sisyphus()
	.triesTo(pushBoulder) // Sets the task
	.indefinitely()       // Max # of attempts = Infinity
	.every(100).ms        // Wait 100 ms in between attempts
	.now()                // Go

sisyphus()
	.triesTo(fetchData)         // Sets the task
	.trying(5).times            // Max # of attempts = 5
	.backingOff(exponentially() // Exponential backoff
		.startingAt(100).ms
		.withFactor(2))
	.now()                      // Returns promise:
	.then(function(response) {
		// ...
	})
	.catch(function(err) {
		// ...
	})

Introduction

Tasks

In Sisyphus, an async task (or simply task) is a function that, when called with no arguments, returns a promise. A call of a task is known as an attempt. If and when the promise fulfills with some value, the task is said to succeed with that value. On the other hand, if and when the promise rejects with some reason, the task is said to fail with that reason.

A Sisyphus instance attempts the given task until an attempt succeeds or until a configured maximum number of attempts is reached.

API

Creation

sisyphus()

Creates and returns a Sisyphus instance. Note that due to the fluent api, it is usually unnecessary to assign the instance to a variable.

Properties

Fleunt no-ops

The .ms, .time and .times properties are references back to the instance. They are provided simply for fluency.

Instance methods

All instance methods, except otherwise sepcified, returns the instance.

.triesTo(task), .tries(task)

Sets the task to be run by the Sisyphus instance. The default task (the one set on instance creation) is one that succeeds with undefined immediately.

.trying(num)

Sets the maximum number of attempts. If num is zero or negative, behavior is unspecified. The default maximum is infinite (no limit).

.once(), .twice(), .thrice(), .indefinitely(), .infinte()

These convenience methods set the maximum number of attempts to the corresponding value.

.waiting(fn), .backingOff(fn)

This sets a function to calculate a wait time between attempts. The function is called with the attempt number that just failed, with the initial attempt being the 0th attempt, and should return the number of milliseconds to wait before the next attempt.

// Constant wait time
sisyphus().waiting(n => 1000)

// Linear backoff
// Note that after the initial attempt fails, the next one will immediately start
sisyphus().waiting(n => 1000 * n)

// The world is your oyster
sisyphus().waiting(n => Math.floor(1000 * n * Math.random()))

.every(ms)

A convenience method for a constant wait time, given in milliseconds

.now(), .$()

Runs the task with retries. Returns a promise.

Since the .now takes no arguments (although it requires the Sisyphus instance as this) and returns a promise, it can itself be thought of as a task -- one that succeeds with the same value if and when any attempt of the inner task succeeds.

If the Sisyphus instance has no maximum attempt limit, then the outer task never fails. If the Sisyphus instance has a maximum attempt limit, then the outer task fails with the same reason if and when the last attempt of the inner task fails.

The high-level algorithm of the outer task is:

  1. Attempt the inner task
  2. If attempt succeeds, the outer task succeeds with the same value as this attempt. END
  3. If attempt fails, and the number of attempts finished >= configured maximum, the outer task fails with the same reason as this attempt. END
  4. Otherwise, call the wait function to get the wait time
  5. Wait that many milliseconds
  6. Go back to step 1

Note on concurrency: Between calling .now/.$ and the return promise settles, do not change any configuration of that Sisyphus instance or call .now/.$ again. The behavior after doing so is unspecified.

Wait time addons

Sisyphus includes some fluently-configurable wait functions.

| | Linear Backoff | Exponential Backoff | | ------ | --------------------------- | -------------------------------- | | source | src/wait/linearly.js | src/wait/exponentially.js | | es | dist/wait/linearly.es.js | dist/wait/exponentially.es.js | | cjs | dist/wait/linearly.cjs.js | dist/wait/exponentially.cjs.js | | extend | dist/wait/linearly.js | dist/wait/exponentially.js |

For the npm package, the above paths are relative to the package root. For UNPKG, the paths are relative to //unpkg.com/sisyphus-retry.

The "extend" format is to be used with the "global" main format. They find a sisyphus global variable and exports to sisyphus.wait.linear and sisyphus.wait.exponentially respectively.

Linear Backoff

linearly([start, [increment]])

Returns a linear backoff function. The wait time after the initial attempt is start milliseconds. Each subsequent attempt has wait time increment milliseconds more than the last.

start and increment both defaults to 0.

Properties

The .ms property of a linear backoff function is a reference to the function itself

Instance methods

The linear backoff functions also have .startingAt(ms) and .incrementingBy(ms) methods to reconfigure the linear backoff fluently.

Exponential Backoff

exponentially([start, [factor]])

Returns an exponential backoff function. The wait time after the initial attempt is start milliseconds. Each subsequent attempt has wait time equal to the last one multiplied by factor.

start and factor defaults to 0 and 1, respectively.

Properties

The .ms property of an exponential backoff function is a reference to the function itself

Instance methods

The exponential backoff functions also have .startingAt(ms) and .withFactor(factor) methods to reconfigure the exponential backoff fluently.

Sisyphus?

Sisyphus is a greek mythology figure who is punished by Zeus to roll a boulder up a hill, but the boulder is enchanted to roll down every time it nears the top, trapping Sisyphus indefinitely.

License

MIT