npm package: @jrc03c/exponential-backoff
Description: a helper class for using exponential back-offs
Latest version: 0.0.4

# intro

a helper class for using exponential back-offs

# installation

```bash
pnpm install --save @jrc03c/exponential-backoff
```

# usage

```js
import { ExponentialBackoffHelper } from "@jrc03c/exponential-backoff"

!(async () => {
  const helper = new ExponentialBackoffHelper()
  let wasSuccessful = false
  let retries = 0

  while (!wasSuccessful && retries < 5) {
    wasSuccessful = await helper.exec(async () => {
      const response = await fetch("...")
      return response.status !== 429
    })

    if (!wasSuccessful) {
      retries++
    }
  }

  console.log("was successful:", wasSuccessful)
  console.log("retry count:", retries)
})()
```

# api

## `ExponentialBackoffHelper`

### `ExponentialBackoffHelper(options)` (constructor)

the `options` object passed into the constructor can have properties corresponding to the instance properties described below.

### properties

#### `downScalar`

a number in the range [0, 1] that will be multipled by the `ms` property value every time a call of the `exec` method is successful. the default value is 0.985.

#### `lastTime`

the last time the `exec` method was called.

#### `ms`

the time in milliseconds that must elapse between calls of functions passed into the `exec` method. in other words, `performance.now() - this.lastTime` must be greater than or equal to `ms` before the function passed into `exec` can be called. the default value is 1.

#### `smoothing`

a number that represents a percentage by which to interpolate between the current `ms` property value and 1. the default value is 0.005.

interpolation can be used to help find an ideal `ms` and prevent oscillations. however, you can disable interpolation entirely by setting `smoothing` to 0.

#### `upScalar`

a number in the range [1, ∞) that will be multiplied by the `ms` property value every time a call of the `exec` method is unsuccessful. the default value is 2.

### methods

#### `exec(fn)`

given a function `fn`, returns a `Promise` that resolves to a boolean indicating whether or not the call of `fn` was successful.

importantly, _you_ define what counts as "successful" or "unsuccessful" by returning `true` or `false` from `fn`. by returning a boolean value from `fn`, you're indicating to the helper that it should up- or down-scale the amount of time it waits between executions. for example, if inside of `fn` you make an http request with `fetch` and the server returns a 429 status (meaning that you've made too many requests in some amount of time and it wants you to slow down), you should return `false` from `fn` so that the _next_ time you invoke the `exec` method, more time will elapse before `fn` is called.

# notes

**1.** this library does not incorporate retries when `exec` calls are unsuccessful.

**2.** i tried to pick sane defaults for all of the properties, but experimentation in your particular context is probably a good idea.

**3.** i don't know how well i've implemented the smoothing / interpolation stuff, but these are the plots (in which the x-axis represents the number of requests made and the y-axis represents the `ms` property of the `ExponentialBackoffHelper` instance) i've been using to convince myself that it's working moderately well:

_without smoothing:_

![](https://i.ibb.co/8DD9sbBS/expo-backoff-1.png)

_with smoothing:_

![](https://i.ibb.co/Lz0gTg6q/expo-backoff-2.png)

as you can see, both plots sort of center around 7.5ms on the y-axis; but the latter plot — representing the scenario in which smoothing / interpolation is enabled — dampens the oscillations and steadily converges on 7.5ms.