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 🙏

© 2024 – Pkg Stats / Ryan Hefner

retry-if

v2.0.0

Published

Conditional function retry with backoff

Downloads

452

Readme

Retry-if

Build Status Coverage Status npm version

Conditional function retry with backoff

This library facilitates the process of re-executing a function under certain error conditions.

A common use case is to retry an API request that returned an error due to rate limiting.

The backoff delay is configurable and may be linear or exponential

Flow

With default settings

on exec -> 0 seconds

first retry -> 1 second later

second retry -> 2 seconds later

...

fifth retry -> 5 seconds later

use the 'exec' function to start the retry chain, it returns a promise

if the 'try' function hasn't been successful by the fifth retry then the promise will reject with an instance of MaxRetryError.

if the 'try' function succeeds at some point during the chain then the promise will resolve with the return value of the 'try' function

The 'if' function is used to control the conditions under which a retry will happen. It receives any error/rejection in the 'try' function and should return/resolve a boolean. Returning true will indicate that a retry should occur, returning false will stop the retry chain and propagate the error to the catch block of the exec promise chain

Error handling

All retry-if library errors inherit from RetryError and have an 'innerError' property that holds the original error thrown in the 'try' function.

When the 'if' function returns false the original error is propagated to the exec catch block

When an unhandled error/rejection occurs in the 'if' function it will propagate to the exec catch block as an instance of IfFunctionError

When a retry chain reaches the max number of retries an instance of MaxRetryError is propagated to the exec catch block

If a deadline is given and the retry chain reaches the deadline an instance of RetryDeadlineError is propagated to the exec catch block

If an unknown growth option is set, an instance of RetryError will be propagated to the exec catch block

Browser/node compatability

This module should work with the following targets:

  • node:
    • 8+
  • browsers:
    • last 2 versions
    • ie11

Example usage

npm install retry-if
import Retry from 'retry-if'

let MockApi = {
    limit: true
    get: function(path) {
        return new Promise((res, rej) => {
            if (path !== 'videos') {
                return rej(new Error('blew up'))
            }
            if (MockApi.limit) {
                MockApi.limit = false
                return rej(new Error('Limiting'))
            }
            return res([1,2,3,4])
        })
    }
}

let retry = new Retry()

retry.if((err) => {
    return (err instanceof Error && err.message === 'Limiting')
})

retry.try(function() { // fails and will not retry because error is not 'Limiting'
    return MockApi.get('something')
}).exec().then(() => {
    // not executed
}).catch((err) => {
    console.log(err) // will be the 'blew up' error from Mock API
})

retry.try(function() { // fails but will retry after delay because error is 'Limiting'
    return MockApi.get('videos')
}).exec().then((val) => {
    console.log(val) // [1,2,3,4]
}).catch((err) => {
    // not executed
})

For ES5 you'll need to use require

var RetryError = require('retry-if').RetryError
var Retry = require('retry-if').default

Options

import Retry from 'retry-if'

let retry = new Retry(options)

Where options is an object with the following properties

baseRetryDelay : Number

growthRate     : Number

growth         : (linear|exponential)

maxRetry       : Integer

deadline       : Moment|ISO String|Number

firstTryDelay  : Number

The defaults are

baseRetryDelay : 1000 // ms

growthRate     : 1000 // ms

growth         : linear

maxRetry       : 5

deadline       : no default

firstTryDelay  : no default

When growth is linear, the value of growthRate is a number of milliseconds to linearly increase on each try

When growth is exponential, the value of growthRate is the multiplier to apply on each try


exponential example

baseRetryDelay : 1000 // ms

growthRate     : 2 // times

growth         : exponential

maxRetry       : 5

This example will re-try the function a maximum of 5 times (for a total of 6 invocations including the initial try)

First call will happen immediately, followed by a re-try after 1 second, then additional retries will occur after 2 seconds, 4 seconds, 8 seconds, etc...


deadline example

baseRetryDelay : 1000 // ms

growthRate     : 0 // ms

growth         : linear

maxRetry       : 100

deadline       : moment().add(30, 's') // moment

or

deadline       : '2016-05-03T17:00:00+08:00' // ISO string

or

deadline       : 3000 // ms

This example will re-try the function a maximum of 100 times or until the deadline is reached

First call will happen immediately, followed by continuous retries after 1 second delays (no growth)

This will continue until 100 retries, or until the deadline is reached


first try delay example

firstTryDelay  : 1000 // ms

This example uses the default options with an additional delay before the first try.

First call will happen after 1 second, followed by a retry after 1 second and subsequent retries inceasing by 1 second each time (2, 3, 4) until 5 retries have been reached